简体   繁体   English

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

[英]Improve performance of a JavaScript function (with an array lookup)

I'm trying to complete a code challenge where I have to decode the keystrokes of a cell phone t9 input into characters to create a text message. 我正在尝试完成代码挑战,我必须将手机t9输入的键击解码为字符以创建文本消息。 The main function (reverse_t9) takes a string of keys such as "44 444" or "999337777" and I need to translate them to their corresponding texts ("hi", or "yes" respectively). 主函数(reverse_t9)使用一串键,例如“44 444”或“999337777”,我需要将它们翻译成相应的文本(分别为“hi”或“yes”)。

I have all the logic down and can generate the correct outputs, but the challenge is telling me that I'm exceeding the time limit which is 4000ms. 我有所有的逻辑,可以生成正确的输出,但挑战告诉我,我超过了4000毫秒的时间限制。 I've found a couple spots to improve performance, but still can't get it under that mark. 我找到了几个提高性能的地方,但仍然无法达到这个标准。 I think the biggest time-waster is my "getLetterFromDigits" function which has to iterate through my array to find the corresponding mapping for a set of keystrokes. 我认为最大的浪费时间是我的“getLetterFromDigits”函数,它必须迭代我的数组才能找到一组击键的相应映射。

Am I missing some other obvious performance problems? 我错过了其他一些明显的性能问题吗? Please let me know if you need more info. 如果您需要更多信息,请告诉我。

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;
}

First, declare your digit mapping outside of the function, so you're reusing the results of that work rather than performing that work every time the function is called. 首先,在函数外部声明数字映射,这样您就可以重用该工作的结果,而不是每次调用函数时都执行该工作。

Secondly, make digitMapping use key/value pairs so you can do a quick lookup based on a given property name rather than having to loop through it. 其次,使digitMapping使用键/值对,以便您可以基于给定的属性名称进行快速查找,而不必循环遍历它。

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

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

Few pointers: 几个指针:

  1. Save length in a variable and use it. 保存变量中的长度并使用它。 Using Array.length will check for every iteration. 使用Array.length将检查每次迭代。
  2. Instead of having array of objects, create 1 mapping object like: 而不是拥有对象数组,创建1个映射对象,如:
{
  "1": [],
  "2": ["a", "b", "c"]
},

and fetch it as digitMapping[mapping[digits.length - 1]] 并将其作为digitMapping[mapping[digits.length - 1]]

  1. Instead of thisKey = keys.substring(i, i + 1); 而不是thisKey = keys.substring(i, i + 1); , you can save characters in a variable like char_arr = keys.split("") and loop over it. ,您可以将字符保存在变量中,如char_arr = keys.split("")并循环遍历它。
  2. You can get rid of 1 iteration(first iteration). 你可以摆脱1次迭代(第一次迭代)。 Just set lastKey = char_arr[0] or lastKey=keys.charAt(0) 只需设置lastKey = char_arr[0]lastKey=keys.charAt(0)
  3. Else part for if (thisKey != lastKey) is not required. if (thisKey != lastKey)其他部分。 If both values are same, you do not need to set lastKey = thisKey; 如果两个值相同,则不需要设置lastKey = thisKey;

Try my version. 试试我的版本。

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');

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM