提高JavaScript函数的性能(使用数组查找)

时间:2016-06-09 15:17:52

标签: javascript arrays performance

我正在尝试完成代码挑战,我必须将手机t9输入的键击解码为字符以创建短信。主函数(reverse_t9)采用一串键,例如" 44 444"或" 999337777"我需要将它们翻译成相应的文本(" hi"或者#34;是"分别)。

我已经完成所有逻辑并且可以生成正确的输出,但挑战是告诉我,我超过了4000毫秒的时间限制。我发现了一些可以提高性能的地方,但仍然无法达到这个标准。我认为最大的浪费时间是我的" getLetterFromDigits"函数必须迭代我的数组才能找到一组击键的相应映射。

我是否遗漏了其他一些明显的性能问题?如果您需要更多信息,请与我们联系。

function reverse_t9(keys) {
    var retVal = "";
    var maxKeystrokes = 3;
    var splitKeystrokes = splitKeystrokesBySpacesAndKeys(keys);

    for (i = 0, numSplits = splitKeystrokes.length; i < numSplits; i++){
        //console.log("THIS SPLIT:");
        //console.log(splitKeystrokes[i]);
        //console.log("THIS LETTER:");
        //console.log(getLetterFromDigits(splitKeystrokes[i]));
        retVal = retVal + getLetterFromDigits(splitKeystrokes[i]);
    }

    return retVal;
}

function splitKeystrokesBySpacesAndKeys(keys) {
    var retVal = [];
    var lastKey = "";
    var thisKey = "";
    var lastSplit = 0;
    var isSpace = 0;

    for (i = 0, numKeys = keys.length; i <= numKeys; i++) {

        thisKey = keys.substring(i, i + 1);

        if (i == 0) {
            // FIRST TIME AROUND, DO NOTHING ELSE, JUST ASSIGN LAST KEY
            lastKey = thisKey;
        } else {
            if (thisKey != lastKey) {
                if (thisKey != " ") {
                    if (lastKey != " ") {
                        retVal.push(keys.substring(lastSplit, i));
                    } else {
                        retVal.push(keys.substring(lastSplit, i - 1));
                    }

                    lastSplit = i;
                }

                lastKey = thisKey;

            } else {
                // KEY DID NOT CHANGE, ASSIGN LAST KEY AND CONTINUE ON
                lastKey = thisKey;
            }
        }
    }

    return retVal;
}

function getLetterFromDigits(digits){
    var retVal;

    var digitMapping = [
    {
        digit: "1",
        mapping: []
    },
    {
        digit: "2",
        mapping: ["a", "b", "c"]
    },
    {
        digit: "3",
        mapping: ["d", "e", "f"]
    },
    {
        digit: "4",
        mapping: ["g", "h", "i"]
    },
    {
        digit: "5",
        mapping: ["j", "k", "l"]
    },
    {
        digit: "6",
        mapping: ["m", "n", "o"]
    },
    {
        digit: "7",
        mapping: ["p", "q", "r", "s"]
    },
    {
        digit: "8",
        mapping: ["t", "u", "v"]
    },
    {
        digit: "9",
        mapping: ["w", "x", "y", "z"]
    },
    {
        digit: "0",
        mapping: ["*"]
    }

    ];

    var digit = digits.substring(0, 1);


    for (i = 0, numMappings = digitMapping.length; i < numMappings; i++){
        if (digitMapping[i].digit == digit){
            retVal = digitMapping[i].mapping[digits.length - 1];
            break;
        }
    }

    return retVal;
}

3 个答案:

答案 0 :(得分:2)

首先,在函数之外声明您的数字映射,这样您就可以重用该工作的结果,而不是每次调用该函数时都执行该工作。

其次,make digitMapping使用键/值对,这样您就可以根据给定的属性名进行快速查找,而不必循环遍历它。

var digitMapping = 
{
    "1": [],
    "2": ["a", "b", "c"],
    ...
};

function getLetterFromDigits(digits){
    var digit = digits.substring(0, 1);
    return digitMapping[digit][digits.length - 1];
}

答案 1 :(得分:1)

几个指针:

  1. 在变量中保存长度并使用它。使用Array.length将检查每次迭代。
  2. 创建1个映射对象,而不是拥有对象数组:
  3. {
      "1": [],
      "2": ["a", "b", "c"]
    },
    

    并将其抓取为digitMapping[mapping[digits.length - 1]]

    1. 您可以将字符保存在thisKey = keys.substring(i, i + 1);之类的变量中,而不是char_arr = keys.split(""),而不是lastKey = char_arr[0]
    2. 你可以摆脱1次迭代(第一次迭代)。只需设置lastKey=keys.charAt(0)if (thisKey != lastKey)
    3. 即可
    4. 不需要lastKey = thisKey;的其他部分。如果两个值相同,则无需设置if (!Monitor.TryEnter(...)) return;

答案 2 :(得分:0)

试试我的版本。

function getMsg(val){
  //split digits to array
  val = val.split('');
  //some internal vars
  var letter = [];
  var last = val[0];
  var msg='';
  for(var i=0,n=val.length;i<n;i++){
    if(val[i]==last)
      //collect sequential digits
      letter.push(val[i]);
    else{
      //new digit 
      msg += digMap[letter[0]][letter.length-1];
      //reinit letter array
      letter=[val[i]];
      last = val[i];
    }
  }
  msg += digMap[letter[0]][letter.length-1];
  return msg; //return decoded
}
//map digits as @Rajesh recommended
var digMap={
  "1":[" "],
  "2":'abc'.split(''),
  "3":'def'.split(''),
  "4":'ghi'.split(''),
  "5":'jkl'.split(''),
  "6":'mno'.split(''),
  "7":'pqrs'.split(''),
  "8":'tuv'.split(''),
  "9":'wxyz'.split(''),
  "0":["*"],
  " ":['']
}
//test functionality
console.time('txt');
console.log(getMsg('999337777'));
//yes
console.timeEnd('txt');