由多个单词(任意顺序)组成的不重复的正则表达式

Regular Expression with multiple words (in any order) without repeat

本文关键字:正则表达式 单词 顺序 任意      更新时间:2023-09-26

我试图在字符串列表上执行排序搜索(使用JavaScript)。列表中的每个字符串都有多个单词。

一个搜索查询也可以包含多个单词,但是单词的顺序不应该是重要的。

例如,对于字符串"This is a random string",查询"trin "和is"应该匹配。然而,这些术语不能重叠。例如,"random random"作为对同一字符串的查询,不应该匹配。

我将根据相关性对结果进行排序,但我自己做这件事应该没有问题,我只是不知道如何构建正则表达式。什么好主意吗?

查询trin and is变成以下正则表达式:

/trin.*(?:and.*is|is.*and)|and.*(?:trin.*is|is.*trin)|is.*(?:trin.*and|and.*trin)/

仅使用正则表达式可能不是一个好主意。一个(纯粹的,计算机科学的)正则表达式"不能计数"。它在任何时候拥有的唯一"内存"是DFA的状态。要匹配任意顺序的多个单词而不重复,你需要2^n个状态。所以可能是一个非常可怕的正则表达式。

(旁白:我提到"纯粹的,计算机科学的"正则表达式,因为大多数实现实际上是一个扩展,并允许您做非正则的事情。我不知道有任何扩展,当然没有在JavaScript中,使做你想做的事情更容易做一个单一的模式。

更好的方法是保留一个字典(JavaScript中的对象),将单词映射到计数。将其初始化为您的单词集,并为每个单词设置适当的计数。您可以使用正则表达式来匹配单词,然后对找到的每个单词在字典中进行相应条目的递减。如果字典在末尾包含任何非0值,或者如果在某个地方尝试过度递减值(或递减不存在的值),则匹配失败。

我完全不确定我是否明白你的意思,所以我就把我的建议贴出来。

var query   = "trin and is",
    target  = "This is a random string",
    search  = { },
    matches = 0;
query.split( /'s+/ ).forEach(function( word ) {
    search[ word ] = true;
});
Object.keys( search ).forEach(function( word ) {
    matches += +new RegExp( word ).test( target );
});
// do something useful with "matches" for the query, should be "3"
alert( matches );

因此,变量matches将包含查询的唯一匹配数。第一个分割循环只是确保不计算"double",因为我们会覆盖搜索对象。第二个循环检查目标字符串中的单个单词,并使用漂亮的+将结果(truefalse)转换为一个数字,因此,匹配时+1或+0。

我一直在寻找这个问题的解决方案,这里提出的解决方案都不够好,所以这就是我想到的:

function filterMatch(itemStr, keyword){
    var words = keyword.split(' '), i = 0, w, reg;
    for(; w = words[i++] ;){
        reg = new RegExp(w, 'ig');
        if (reg.test(itemStr) === false) return false;   // word not found
        itemStr = itemStr.replace(reg, '');              // remove matched word from original string
    }
    return true;
}
// test
filterMatch('This is a random string', 'trin and is');   // true
filterMatch('This is a random string', 'trin not is');   // false