Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/410.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在javascript中搜索字符串的最快方法_Javascript - Fatal编程技术网

在javascript中搜索字符串的最快方法

在javascript中搜索字符串的最快方法,javascript,Javascript,我的页面上有一个隐藏的字段,用于存储以空格分隔的电子邮件列表。 在那个领域我最多可以收到500封电子邮件 如果给定的电子邮件已经存在于该列表中,那么最快的搜索方式是什么? 我需要在一个循环中搜索多封电子邮件 使用正则表达式查找匹配项 使用indexOf() 将列表转换为 javascript字典,然后 搜寻 如果这是完全相同的,请让我知道另一个问题。 谢谢 编辑: 谢谢大家的宝贵意见和回答。 基本上,我的用户有一个以db为单位的电子邮件列表(0-500)。 用户将看到自己的联系人列表。 然后,用

我的页面上有一个隐藏的字段,用于存储以空格分隔的电子邮件列表。 在那个领域我最多可以收到500封电子邮件

如果给定的电子邮件已经存在于该列表中,那么最快的搜索方式是什么? 我需要在一个循环中搜索多封电子邮件

  • 使用正则表达式查找匹配项

  • 使用indexOf()

  • 将列表转换为 javascript字典,然后 搜寻
  • 如果这是完全相同的,请让我知道另一个问题。 谢谢

    编辑: 谢谢大家的宝贵意见和回答。 基本上,我的用户有一个以db为单位的电子邮件列表(0-500)。 用户将看到自己的联系人列表。 然后,用户可以从联系人列表中选择一封\多封电子邮件添加到列表中。 我想在客户端确保他没有添加重复的电子邮件。 整个操作都是由ajax驱动的,因此需要jsvascript。

    indexOf()
    可能是最快的。请记住,您需要搜索两种可能的情况:

    var existingEmails = "email1, email2, ...";
    var newEmail = "somethingHere@email.com";
    var exists = (existingEmails.indexOf(newEmail + " ") >= 0) || (existingEmails.indexOf(" " + newEmail ) > 0);
    

    你问的问题有太多未说明的变量,我们无法回答。例如,您希望执行多少次此搜索?只有一次?一百次?这是一个固定的电子邮件列表,还是每次都会改变?您是通过页面加载电子邮件,还是通过AJAX加载电子邮件

    如果您正在执行多个搜索,或者电子邮件加载了该页面,那么您最好创建一个名称字典,并使用Javascript in操作符

    如果从某个页外源获取字符串,并且只搜索一次,那么
    indexOf
    可能会更好

    在所有情况下,如果你真的关心速度,你最好进行一次测试


    但是我会问“你为什么关心速度?”这是一个网页,在这个网页上,加载页面是以网络速度进行的;搜索以或多或少的本地处理器速度进行。这一次搜索不大可能对页面的行为产生明显的影响。

    这里有一点解释:

    执行字典查找相对比较复杂-与(比如)有很多键时按键线性查找相比非常快,但比直接数组查找复杂得多。它必须计算密钥的散列,然后计算出应该在哪个bucket中,可能需要处理重复的散列(或重复的bucket),然后检查是否相等

    和往常一样,为工作选择正确的数据结构——如果你真的可以通过索引到一个数组(或列表)中而逃脱,那么是的,这将非常快


    以上内容摘自@Jon Skeet的一篇博文。

    答案是:视情况而定

    • 这取决于你实际想要测量什么
    • 这取决于你搜索的数量与你搜索的数量之间的关系
    • 这取决于JavaScript实现。不同的实现通常具有完全不同的性能特征。这是“不要过早优化”规则特别适用于跨实现JavaScript的众多原因之一
    …但如果您查找的内容比总数少得多,则可能是
    String 35; indexOf
    ,除非您可以创建一次字典并重用它(不仅仅是查找X个条目的一个循环,而是查找X个条目的每个循环,我倾向于怀疑这是您的用例),在这种情况下,构建500键字典并使用它会更快

    我整理了一个示例,比较了在一个包含500个空格分隔的唯一条目的字符串中查找五个字符串的结果。请注意,jsperf页面比较了一些苹果和橙子(我们可以忽略设置的情况以及我们忽略的设置类型),但是jsperf对于拆分它来说是一件痛苦的事情,我决定把它作为一个练习留给读者

    在我对你所做的测试中,Chrome、Firefox、IE6、IE7和IE9做的
    String#indexOf
    最快。Opera执行了
    RegExp交替
    最快的操作。(请注意,IE6和IE7没有
    数组#indexOf
    ,其他的都有。)如果您可以忽略字典设置时间,那么使用字典就是轻而易举的赢家

    以下是准备代码:

    // ==== Main Setup
    var toFind = ["aaaaa100@zzzzz", "aaaaa200@zzzzz", "aaaaa300@zzzzz", "aaaaa400@zzzzz", "aaaaa500@zzzzz"];
    var theString = (function() {
     var m, n;
    
     m = [];
     for (n = 1; n <= 500; ++n) {
      m.push("aaaaa" + n + "@zzzzz");
     }
     return m.join(" ");
    })();
    
    // ==== String#indexOf (and RegExp) setup for when we can ignore setup
    var preppedString = " " + theString + " ";
    
    // ==== RegExp setup for test case ignoring RegExp setup time
    var theRegExp = new RegExp(" (?:" + toFind.join("|") + ") ", "g");
    
    // ==== Dictionary setup for test case ignoring Dictionary setup time
    var theDictionary = (function() {
     var dict = {};
     var index;
     var values = theString.split(" ");
     for (index = 0; index < values.length; ++index) {
      dict[values[index]] = true;
     }
     return dict;
    })();
    
    // ==== Array setup time for test cases where we ignore array setup time
    var theArray = theString.split(" ");
    
    字符串#indexOf
    (忽略设置)
    测试,在该测试中,我们忽略在大字符串的两端放置空格的(小)开销:

    var index;
    for (index = 0; index < toFind.length; ++index) {
     if (preppedString.indexOf(toFind[index]) < 0) {
      throw "Error";
     }
    }
    
    RegExp
    交替(忽略设置)
    测试,我们忽略设置RegExp对象和在大字符串两端放置空格所需的时间(我认为这不适用于您的情况,您要查找的地址是静态的):

    字典测试:

    var index;
    for (index = 0; index < toFind.length; ++index) {
     if (theString.indexOf(toFind[index]) < 0) {
      throw "Error";
     }
    }
    
    // Note: In real life, you'd have to escape the values from toFind
    // to make sure they didn't have special regexp chars in them
    var regexp = new RegExp(" (?:" + toFind.join("|") + ") ", "g");
    var match, counter = 0;
    var str = " " + theString + " ";
    for (match = regexp.exec(str); match; match = regexp.exec(str)) {
     ++counter;
    }
    if (counter != 5) {
     throw "Error";
    }
    
    var dict = {};
    var index;
    var values = theString.split(" ");
    for (index = 0; index < values.length; ++index) {
     dict[values[index]] = true;
    }
    for (index = 0; index < toFind.length; ++index) {
     if (!(toFind[index] in dict)) {
      throw "Error";
     }
    }
    
    Array#indexOf
    测试(注意,一些非常旧的JavaScript实现可能没有
    Array#indexOf
    ):


    与其寻找最快的解决方案,您首先需要确保您实际拥有一个正确的解决方案。因为有四种情况会出现电子邮件地址,而简单的搜索可能会失败:

  • 单独:
    user@example.com
  • 开始时:
    user@example.com…
  • 最后:
    。。。user@example.com
  • 中间:
    。。。user@example.com…
  • 现在,让我们分析每个变量:

  • 要允许任意输入,您需要正确地转义输入。可以使用以下方法执行此操作:

    RegExp.quote = function(str) {
        return str.toString().replace(/(?=[.?*+^$[\]\\(){}-])/g, "\\");
    };
    
    要匹配所有四种情况,可以使用以下模式:

    /(?:^|\ )user@example\.com(?![^\ ])/
    
    因此:

  • 使用
    indexOf
    稍微复杂一些,因为您需要手动检查边界:

    var pos = haystack.indexOf(needle);
    if (pos != -1 && (pos != 0 && haystack.charAt(pos-1) !== " " || haystack.length < (pos+needle.length) && haystack.charAt(pos+needle.length) !== " ")) {
        pos = -1;
    }
    var inList = pos != -1;
    

  • 现在要测试哪种变体最快,您可以在进行测试。

    我知道这是一个老问题,但这里有一个答案供未来可能需要的人使用
    var index;
    for (index = 0; index < toFind.length; ++index) {
     if (theArray.indexOf(toFind[index]) < 0) {
      throw "Error";
     }
    }
    
    RegExp.quote = function(str) {
        return str.toString().replace(/(?=[.?*+^$[\]\\(){}-])/g, "\\");
    };
    
    /(?:^|\ )user@example\.com(?![^\ ])/
    
    var inList = new RegExp("(?:^| )" + RegExp.quote(needle) + "(?![^ ])").test(haystack);
    
    var pos = haystack.indexOf(needle);
    if (pos != -1 && (pos != 0 && haystack.charAt(pos-1) !== " " || haystack.length < (pos+needle.length) && haystack.charAt(pos+needle.length) !== " ")) {
        pos = -1;
    }
    var inList = pos != -1;
    
    var dict = {};
    haystack.match(/[^\ ]+/g).map(function(match) { dict[match] = true; });
    var inList = dict.hasOwnProperty(haystack);
    
    console.time('a');
    var a=((Math.random()*1e8)>>0).toString(16);
    for(var i=0;i<1000;++i)a=a+' '+((Math.random()*1e8)>>0).toString(16)+((Math.random()*1e8)>>0).toString(16)+((Math.random()*1e8)>>0).toString(16)+((Math.random()*1e8)>>0).toString(16);
    console.timeEnd('a');
    console.time('b');
    var b=(' '+a).indexOf(((Math.random()*1e8)>>0).toString(16));
    console.timeEnd('b');
    console.log([a,b]);