在 JavaScript 中检查字符串是不是包含另一个子字符串的最快方法?

Posted

技术标签:

【中文标题】在 JavaScript 中检查字符串是不是包含另一个子字符串的最快方法?【英文标题】:Fastest way to check a string contain another substring in JavaScript?在 JavaScript 中检查字符串是否包含另一个子字符串的最快方法? 【发布时间】:2011-07-14 20:29:35 【问题描述】:

我正在处理 javascript 的性能问题。所以我只想问:检查一个字符串是否包含另一个子字符串的最快方法是什么(我只需要布尔值)?您能否提出您的想法和示例 sn-p 代码?

【问题讨论】:

你问的是固定子串,还是需要正则表达式(我对regex标签的使用有点困惑)? 这篇文章会很有帮助..***.com/questions/1789945/javascript-string-contains 如何将字符串拆分为围绕空格的数组并进行数组交集? ***.com/questions/1885557/… jsben.ch/#/aWxtF 【参考方案1】:

这对你有用吗?

string1.indexOf(string2) >= 0

编辑:如果 string2 包含重复的模式,这可能不会比 RegExp 快。在某些浏览器上,indexOf 可能比 RegExp 慢得多。见 cmets。

编辑 2:当字符串很长和/或包含重复模式时,RegExp 可能比 indexOf 更快。请参阅 cmets 和 @Felix 的回答。

【讨论】:

但这与其他方法相比如何?这是最快的,还是只是众多方法中的一种? 这应该很快,因为它是由 JavaScript 本身实现的(即它运行本机代码)。任何其他基于 JavaScript 代码的方法都会比较慢。如果您知道确切的字符串,则正则表达式可能会更快一些(因为 JavaScript 引擎不必遍历原型链来查找 .indexOf)。 如果您需要不区分大小写的搜索,那么您肯定需要构建一个 RegExp 对象并调用test 刚刚在 Safari 中进行了测试。 indexOf 比任何其他方法都慢一个数量级。所以实际上不能说哪种方法更快。它因浏览器而异。 @Felix,这是一个很好的观察结果(在您亲自尝试之前永远不要相信任何东西)!我模糊地记得在有很多重复模式的字符串中说的东西,正则表达式应该比简单的循环比较实现执行得更快,因为正则表达式被编译到状态机中并且它可以比简单循环更快地回溯——它必须总是回溯——跟踪到下一个字符。 +1 进行实验并将其推出!【参考方案2】:

你有三种可能:

    Regular expression:

     (new RegExp('word')).test(str)
     // or
     /word/.test(str)
    

    indexOf:

     str.indexOf('word') !== -1
    

    includes:

     str.includes('word')
    

Regular expressions seem to be faster(至少在 Chrome 10 中)。

Performance test - short haystackPerformance test - long haystack


**2011 年更新:**

不能肯定地说哪种方法更快。浏览器之间的差异是巨大的。虽然在 Chrome 10 中 indexOf 似乎更快,但在 Safari 5 中,indexOf 显然比任何其他方法都慢。

你必须亲自去看看和尝试。这取决于您的需求。例如,不区分大小写的搜索使用正则表达式要快得多。


2018 年更新:

为了避免人们自己运行测试,以下是大多数常见浏览器的当前结果,百分比表示性能比下一个最快结果(因浏览器而异)有所提高:

Chrome: indexOf(快约 98%)<-- wow Firefox: 缓存正则表达式(快约 18%) IE11: 缓存 RegExp(快约 10%) Edge: indexOf(快约 18%) Safari:缓存正则表达式(快~​​0.4%)

请注意,缓存的 RegExp 是:var r = new RegExp('simple'); var c = r.test(str);,而不是:/simple/.test(str)

【讨论】:

只有在事先知道要搜索的文本(即不存储在变量中)的情况下,这可能会快一点,因为正则表达式是由 JavaScript 引擎在解析时创建的。如果要在另一个字符串变量中搜索包含在变量中的字符串,indexOf 是最快的,因为您需要创建一个 RegExp 对象并处理字符串以转义特殊字符等。 根据经验,如果您首先在搜索的任何内容上使用 .toLowerCase,则 indexOf 可以更快地进行不区分大小写的搜索 我正在编写一个 Office 2013 应用程序,使用 Microsoft 的 Office Javascript API,并且使用 indexOf 不起作用。我不确定为什么。虽然使用正则表达式。这是一个边缘案例,但其他人可能会遇到同样的问题。 有什么理由 substr() 不是可能的解决方案之一?我猜它在许多情况下都比 RegEx 解决方案快得多。我不知道它与 indexOf() 相比如何(因此,如果您因为它的性能总是比 indexOf() 差而忽略它,那没关系,也许可以添加一个注释来达到这种效果。)编辑: this JSperf link 显示了一些有趣的结果。简短版本:indexOf() 是所有方法中最快的,但这可能会因字符串长度和任何重复模式而异。 @Bison:如果您已经知道在哪里查找,则只能使用 substr。我只关注通用解决方案。【参考方案3】:

对于查找简单字符串,使用 indexOf() 方法和使用正则表达式几乎相同:http://jsperf.com/substring - 所以选择看起来更容易编写的那个。

【讨论】:

【参考方案4】:

使用.match()方法串起来很简单。

var re = /(AND|OR|MAYBE)/;
var str = "IT'S MAYBE BETTER WAY TO USE .MATCH() METHOD TO STRING";
console.log('Do we found something?', Boolean(str.match(re)));

祝你有美好的一天,先生!

【讨论】:

当有test 方法时,没有理由match...查看最佳答案。【参考方案5】:

我发现使用简单的 for 循环,遍历字符串中的所有元素并使用 charAt 进行比较比 indexOfRegex 执行得更快。代码和证明可在JSPerf 获得。

ETA:根据 jsperf.com 上列出的 Browser Scope 数据,indexOfcharAt 在 Chrome Mobile 上的表现同样糟糕

【讨论】:

奇怪的是手工制作的功能比内置的要好,但我想这是因为针只有一个字符。还是…… 在 Apple iPad (ios 7.1.1) 上的 Chrome Mobile 36.0.1985.57 中测试。 IndexOf 更快。对不起 @rpax CharAt 在所有平台上仍然明显更快(基于 jsperf 的历史记录)除了对于 Chrome Mobile,其中 IndexOf 和 CharAt 与桌面。 我想看看它在 NodeJS 中的表现如何,这也不是一个很好的例子,因为你只是在寻找一个字符而不是一个子字符串。 这根本不是一个有效的答案。您不是在搜索子字符串,而是在搜索单个字符【参考方案6】:

在 ES6 中,includes() 方法用于确定一个字符串是否可以在另一个字符串中找到,并根据需要返回 truefalse

var str = 'To be, or not to be, that is the question.';

console.log(str.includes('To be'));       // true
console.log(str.includes('question'));    // true
console.log(str.includes('nonexistent')); // false

这里是jsperf

var ret = str.includes('one');

还有

var ret = (str.indexOf('one') !== -1);

从 jsperf 的结果来看,两者的表现似乎都不错。

【讨论】:

我可以在里面使用“regex”,作为包含的参数吗?喜欢:str.includes("x|y");在同一个调用中搜索文字“x”或“y”。 @Patrick,根据包含文档,您不能在其中使用 regex。解决您的问题的一种方法,str.includes("x") || str.includes('y') 由于 Chrome 59 JavaScript 改进,indexOf 明显快于 includes(快 1600% 以上)。目前尚不清楚 4400 万次迭代/秒和 777+ 百万次 i/秒之间的差异如何影响实际性能,但移动设备的好处可能足以让indexOf 成为理想选择。【参考方案7】:

我为你做了一个 jsben.ch http://jsben.ch/#/aWxtF ...似乎 indexOf 有点快。

【讨论】:

我将其分叉以进行更强大的测试。在 Firefox 中,我发现方法之间的差异不到 1%,但在 Chrome 上,indexOf 击败了竞争对手,速度提高了 500% 以上。 我想知道布尔测试和 != -1 之间是否有很大区别【参考方案8】:

最快的

    (ES6) 包括
var string = "你好", 子串=“lo”; string.includes(子字符串);
    ES5 及更早版本 indexOf
var string = "你好", 子串=“lo”; string.indexOf(substring) !== -1;

http://jsben.ch/9cwLJ

【讨论】:

以上是关于在 JavaScript 中检查字符串是不是包含另一个子字符串的最快方法?的主要内容,如果未能解决你的问题,请参考以下文章

检查一个数组是不是包含 JavaScript 中另一个数组的任何元素

检查一个数组是不是包含 JavaScript 中另一个数组的任何元素

如何在 JavaScript 中检查字符串是不是包含数字和特殊字符?

如何使用 PHP 检查一个单词是不是包含在另一个字符串中?

检查一个字符串是不是可以由 Javascript 中另一个字符串中的字符组成

puppet 中用于检查字符串是不是包含另一个字符串的函数