我有这个正则表达式:
"(WORD1.*WORD2.*WORD3)|(WORD1.*WORD3.*WORD2)|(WORD2.*WORD1.*WORD3)|(WORD2.*WORD3.*WORD1)|(WORD3.*WORD1.*WORD2)|(WORD3.*WORD2.*WORD1)"
它与这些词匹配:
WORD1WORD2WORD3 WORD1AWORD2BWORD3C WORD3WORD1WORD2 WORD1WORD2WORD3WORD1
但不是这些话:
WORD1WORD1WORD2 WORD1AWORD1BWORD2C
当该正则表达式找到包含任意顺序的 3 个单词(WORD1
、WORD2
、WORD3
)的字符串时,它就会匹配。
我想用更多的单词做同样的事情,但问题是正则表达式的大小随着单词的数量呈指数增长。 是否可以简化此正则表达式的构造方式来解决此问题(大小不会呈指数增长)?
P粉6638838622024-02-27 16:51:16
简单地迭代所有字符串并过滤掉所有不包含所有关键字的字符串:
(可以在下面的代码片段中找到更简洁的版本)
function findMatch(strings, keywords) { const result = []; for (const string of strings) { if (keywords.every(keyword => string.includes(keyword))) { result.push(string); } } return result; }
尝试一下:
console.config({ maximize: true }); function findMatch(strings, keywords) { return strings.filter( string => keywords.every(keyword => string.includes(keyword)) ); } const testcases = [ 'WORD1WORD2WORD3', 'WORD1AWORD2BWORD3C', 'WORD3WORD1WORD2', 'WORD1WORD2WORD3WORD1', 'WORD1WORD1WORD2', 'WORD1AWORD1BWORD2C' ]; const keywords = [ 'WORD1', 'WORD2', 'WORD3' ]; console.log(findMatch(testcases, keywords));
sssccc
P粉9981006482024-02-27 11:50:29
您可以对每个单词使用正向前瞻。
/(?=.*WORD1)(?=.*WORD2)(?=.*WORD3).*/
下面的更高性能版本指定起始锚点,并且在验证前瞻后仅匹配单个字符。根据OP的要求,此技术仅适用于matching
,而不适用于extraction
。
/^(?=.*WORD1)(?=.*WORD2)(?=.*WORD3)./
正向先行就像一个门,只有当括号内指定的匹配存在时,它才会继续,但它不会消耗或捕获它匹配的内容——它总是零长度。如果您“向前看”以查看每个单词前面是否存在 .*
,那么这些单词的顺序并不重要。如果每个单词为真,则继续进行,而不会使用任何内容进行匹配。 p>
如果您只关心内容是否匹配,那么两个表达式之间唯一的实质性区别就是它们花费的时间。假设您的内容中只有 3 个必需单词中的 2 个。除非解释表达式的软件能够识别尝试是徒劳的,否则它可能会在第一个位置查找三个单词“失败”,然后在第二个位置尝试“失败”,等等,直到到达最后一个位置才放弃。通过指定^
,只会在第一个位置进行检查,节省了其他不必要检查的时间。当您只是寻找内容中是否存在所有单词的真/假答案时,从末尾删除 *
可以防止一些不必要的捕获。