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

IT技术 javascript regex substring
2021-02-08 17:49:39

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

6个回答

你有三种可能:

  1. 正则表达式

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

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

     str.includes('word')
    

正则表达式似乎更快(至少在 Chrome 10 中)。

性能测试 - 短干草堆
性能测试 - 长干草堆


**2011 年更新:**

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

你必须看到并尝试自己。这取决于您的需求。例如,不区分大小写的搜索使用正则表达式会更快。


2018 年更新:

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

Chrome: indexOf(快 98%)<-- wow
Firefox:缓存 RegExp(快 18%)
IE11:缓存 RegExp(快 10%)
Edge: indexOf(快 18%)
Safari:缓存 RegExp(快 0.4%)

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

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

最快的

  1. (ES6)包括
    var string = "你好",
    子串 = "lo";
    字符串。包含(子字符串);
  1. ES5 及更早的indexOf
    var string = "你好",
    子串 = "lo";
    string.indexOf(substring) !== -1;

http://jsben.ch/9cwLJ

在此处输入图片说明

这对你有用吗?

string1.indexOf(string2) >= 0

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

编辑 2:当字符串很长和/或包含重复模式时,RegExp 可能比 indexOf 快。查看评论和@Felix 的回答。

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

在 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中显示的结果,似乎它们都表现良好。

作为 Chrome 59 JavaScript 改进的结果,indexOf明显快于includes(快 1600%)。目前尚不清楚 4400 万次迭代/秒和777+ 百万次i/秒的差异如何影响现实世界的性能,但移动设备可能会带来足够的好处,这indexOf应该是理想的选择。
2021-03-21 17:49:39
@Patrick,根据包含文档,您不能regex在其中使用一种解决您的问题的方法,str.includes("x") || str.includes('y')
2021-04-03 17:49:39
我可以在里面使用“regex”作为包含的参数吗?像:str.includes("x|y"); 在同一个调用中搜索文字“x”或“y”。
2021-04-10 17:49:39

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

ETA:根据 jsperf.com 上列出的浏览器范围数据indexOfcharAt两者在 Chrome Mobile 上的表现都同样糟糕

这根本不是一个有效的答案。您不是在搜索子字符串,而是在搜索单个字符的出现
2021-03-18 17:49:39
@rpax CharAt 在所有平台上的速度仍然明显更快(基于 jsperf 的历史),除了Chrome Mobile,与桌面相比,IndexOf 和 CharAt 的性能同样非常差。
2021-03-19 17:49:39
我想看看它在 NodeJS 中的表现,而且这也不是一个很好的例子,因为您只是在寻找一个字符与一个子字符串。
2021-04-01 17:49:39
奇怪的是手工制作的功能比内置的好,但我想这是因为针只有一个字符。仍然...
2021-04-05 17:49:39
在 Apple iPad (iOS 7.1.1) 上的 Chrome Mobile 36.0.1985.57 中测试。IndexOf 更快。对不起
2021-04-07 17:49:39