如何使这个正则表达式简化?
P粉710454910
P粉710454910 2024-02-26 18:49:18
0
2
371

我有这个正则表达式:

"(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 个单词(WORD1WORD2WORD3)的字符串时,它就会匹配。

我想用更多的单词做同样的事情,但问题是正则表达式的大小随着单词的数量呈指数增长。 是否可以简化此正则表达式的构造方式来解决此问题(大小不会呈指数增长)?

P粉710454910
P粉710454910

全部回复(2)
P粉663883862

简单地迭代所有字符串并过滤掉所有不包含所有关键字的字符串:

(可以在下面的代码片段中找到更简洁的版本)

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粉998100648

您可以对每个单词使用正向前瞻。

/(?=.*WORD1)(?=.*WORD2)(?=.*WORD3).*/

下面的更高性能版本指定起始锚点,并且在验证前瞻后仅匹配单个字符。根据OP的要求,此技术仅适用于matching,而不适用于extraction

/^(?=.*WORD1)(?=.*WORD2)(?=.*WORD3)./

正向先行就像一个门,只有当括号内指定的匹配存在时,它才会继续,但它不会消耗或捕获它匹配的内容——它总是零长度。如果您“向前看”以查看每个单词前面是否存在 .*,那么这些单词的顺序并不重要。如果每个单词为真,则继续进行,而不会使用任何内容进行匹配。 p>

如果您只关心内容是否匹配,那么两个表达式之间唯一的实质性区别就是它们花费的时间。假设您的内容中只有 3 个必需单词中的 2 个。除非解释表达式的软件能够识别尝试是徒劳的,否则它可能会在第一个位置查找三个单词“失败”,然后在第二个位置尝试“失败”,等等,直到到达最后一个位置才放弃。通过指定^,只会在第一个位置进行检查,节省了其他不必要检查的时间。当您只是寻找内容中是否存在所有单词的真/假答案时,从末尾删除 * 可以防止一些不必要的捕获。

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责声明 Sitemap
PHP中文网:公益在线PHP培训,帮助PHP学习者快速成长!