具有多个单词(以任何顺序)的正则表达式,无需重复

时间:2011-10-10 22:48:30

标签: javascript regex search

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

搜索查询也可能包含多个单词,但单词的顺序无关紧要。

例如,在字符串“这是随机字符串”上,查询“trin和”应该匹配。但是,这些术语不能重叠。例如,“random random”作为对同一字符串的查询不应匹配。

我将根据相关性对结果进行排序,但我自己也应该没有问题,我只是无法弄清楚如何建立正则表达式。有什么想法吗?

4 个答案:

答案 0 :(得分:4)

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

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

换句话说,不要为此使用正则表达式。

答案 1 :(得分:3)

使用正则表达式执行此操作可能不是一个好主意。一个(纯粹的,计算机科学)正则表达式“不能算”。它在任何时候唯一的“记忆”就是DFA的状态。要按任意顺序匹配多个单词而不重复,您需要大约2 ^ n个状态。所以可能是一个非常可怕的正则表达式。

(旁白:我提到“纯粹的,计算机科学”的正则表达式,因为大多数实现实际上都是一个扩展,让你做一些非常规的事情。我不知道任何扩展,当然没有JavaScript,用一种模式做你想要做的事情。“

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

答案 2 :(得分:1)

我完全不确定我是否让你在那里,所以我会发布我的建议。

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将包含查询的唯一匹配数。第一个分割循环只是确保没有计算“双精度”,因为我们会覆盖我们的搜索对象。第二个循环检查目标字符串中的单个单词,并使用漂亮的+将结果(truefalse)转换为数字,因此,匹配时为+1或+0。

答案 3 :(得分: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