【问题标题】:Optimize javascript code on searching for matches in array优化 javascript 代码在数组中搜索匹配项
【发布时间】:2012-12-31 00:14:19
【问题描述】:

基本上,我需要从包含在主字符串中的数组中获取单词

我在这里有一个循环代码,但我认为有一个单行代码可以做到这一点。 我需要对代码进行优化,不仅要优化代码长度,还要优化性能。

谢谢

var aValidWords = ["ex", "exes", "expert", 
                   "experts", "expertise", "sex", "sexes", 
                   "exchange", "change", "changes"];
var sMainWord = "expertsExchange";
var aPossibleWords = new Array();

var sMainWordLower = sMainWord.toLowerCase();
for(i=0; i < aValidWords.length; i++){
    var sCurrentWord = aValidWords[i].toLowerCase();
    if(sMainWordLower.indexOf(sCurrentWord) != -1){
        aPossibleWords.push(aValidWords[i]);
    }
}

document.write(aPossibleWords.join("<br />"));

【问题讨论】:

  • 我的第一个想法是将数组转换为正则表达式。但这只会找到匹配的子字符串,而不是告诉您找到了哪些有效单词。如果有效词中没有重叠的子串就可以了,但是它们有很多。
  • 你可以创建一个映射表。由于 "experts" 包含 "ex"、"expert" 和 "experts" 本身,因此您只需处理 "experts" 即可知道三个单词是有效的。
  • @asgoth 事情是,sMainWord 会不时更改。
  • 我知道,但它独立于主词。假设你有这样的映射表(伪):(专家 -> 专家,专家,前),(专家 -> 专家,前),(交换 -> 变化),......那么你只需要遍历最大的首先是单词,如果这些最大的单词中的任何一个匹配,您也可以从映射表中删除较小的单词。
  • 除非映射表来自服务器,否则不;)否则一个小的优化:用 [] 替换 new Array()

标签: javascript optimization


【解决方案1】:

我比较了三种可能的实现方式:

备选方案 1 - 使用 for 循环:

function alternative1(aValidWords, sMainWordLower) {
    var aPossibleWords1 = [];
    for(i=0; i < aValidWords.length; i++){
        if(sMainWordLower.indexOf(aValidWords[i]) != -1){
            aPossibleWords1.push(aValidWords[i]);
        }
    }
    return aPossibleWords1;
}

替代方案 2 - 使用 jQuery grep 函数:

function alternative2(aValidWords, sMainWordLower) {
    return $.grep(aValidWords, function(word) {
              return sMainWordLower.indexOf(word) != -1;                    
         }
    )
}

替代方案 3 - 使用 JavaScript 原生 filter 方法(IE9、Chrome、Firefox、Opera、Safari):

function alternative3(aValidWords, sMainWordLower) {
    return aValidWords.filter(function(word) {
              return sMainWordLower.indexOf(word) != -1;                    
         }
    )
}

我使用 Chrome 配置文件工具测量了执行时间。每个备选方案使用随机的百万字数组执行 10 次。结果是:

  • 备选方案 1:20 次处决 -> 21.68 秒
  • 备选方案 2:20 次处决 -> 26.31 秒
  • 替代方案 3:20 次处决 -> 34,66 秒

我对原生 JavaScript Filter 函数如此缓慢的事实感到惊讶。

如果您不想自己测量执行时间,可以使用jsFiddle - 脚本需要一些时间才能完成。

一般来说,这三种选择是最简单的。如果这些执行时间适合您,请使用其中一个,否则@Pumbaa80 的答案是正确的。

[更新]

关于结果的解释(为什么 JQuery grep 函数比原生 JavaScript 过滤函数更快)请看这个question/answer。 感谢@Alexander,jsFiddle 代码也被移植到jsPerf

【讨论】:

  • 我曾经想过,但我担心性能不会是最佳的。 +1 用于更短的代码;
【解决方案2】:

我认为你的代码不错。

如果您真的担心性能,您可能想尝试一些复杂的方法,例如Boyer-Moore。 但是,如果你只有少量的模式和相对较短的字符串,那么初始化开销大于好处,所以你应该坚持简单的方法。见维基百科的对照表http://en.wikipedia.org/wiki/String_searching_algorithm#Single_pattern_algorithms

【讨论】:

    【解决方案3】:

    这个循环肯定比你所拥有的更简洁,但值得在各种浏览器中运行一些测试以找出哪个更快。我想 Regex matching 可能更快,但我很好奇编译 Regex 是否有任何性能损失。

    for(var i=0; i<aValidWords.length; i++) {
        if (new RegExp(aValidWords[i], 'i').test(sMainWord))
            aPossibleWords.push(aValidWords[i]);
    }
    

    【讨论】:

    • 好吧,使用正则表达式会更慢,但是对于较短的代码 +1 :-)
    猜你喜欢
    • 2021-11-16
    • 1970-01-01
    • 2015-09-15
    • 1970-01-01
    • 1970-01-01
    • 2011-02-14
    • 1970-01-01
    • 1970-01-01
    • 2012-08-15
    相关资源
    最近更新 更多