stema 的答案在技术上是正确的,但它根本没有考虑性能。前瞻非常慢(在正则表达式的上下文中,它快如闪电)。即使使用当前的逻辑,正则表达式也不是最优的。
所以这里有一些测量值,是在包含所有三个单词的较大字符串上计算的,运行搜索 1000 次并使用四种不同的方法:
stema 的正则表达式
/^(?=.*\bmeat\b)(?=.*\bpasta\b)(?=.*\bdinner\b).+/
结果:605ms
优化的正则表达式
/^(?=.*?\bmeat\b)(?=.*?\bpasta\b)(?=.*?\bdinner\b)/
使用惰性匹配并且不需要 end all 选择器
结果:291ms
置换正则表达式
/(\bmeat\b.*?(\bpasta\b.*?\bdinner\b|\bdinner\b.*?\bpasta\b)|\bpasta\b.*?(\bmeat\b.*?\bdinner\b|\bdinner\b.*?\bmeat\b)|\bdinner\b.*?(\bpasta\b.*?\bmeat\b|\bmeat\b.*?\bpasta\b))/
结果:56ms
这很快,因为第一个模式正在匹配,如果最后一个模式匹配,它会比前瞻模式(300 毫秒)更慢
正则表达式数组
var regs=[/\bmeat\b/,/\bpasta\b/,/\bdinner\b/];
var result = regs.every(reg=>reg.test(text));
结果:26ms
请注意,如果字符串被设计为不匹配,则结果为:
- 521毫秒
- 220毫秒
- 161ms - 慢得多,因为它必须经过所有分支
- 14毫秒
如您所见,在所有情况下,仅使用循环都会快一个数量级,更不用说更容易阅读了。
最初的问题是要求一个正则表达式,所以我的答案是排列正则表达式,但我不会使用它,因为它的大小会随着搜索词的数量呈指数增长。
此外,在大多数情况下,这个性能问题是学术性的,但有必要强调一下。