Регулярное выражение с несколькими словами (в любом порядке) без повторения - PullRequest
5 голосов
/ 11 октября 2011

Я пытаюсь выполнить сортировку (используя JavaScript) по списку строк. Каждая строка в списке состоит из нескольких слов.

Поисковый запрос может также включать несколько слов, но порядок слов не должен иметь значения.

Например, для строки "Это случайная строка" , запрос "trin и is" должен совпадать. Однако эти условия не могут пересекаться. Например, "random random" как запрос к той же строке не должен совпадать.

Я собираюсь сортировать результаты по релевантности, но у меня не должно возникнуть никаких проблем, я просто не могу понять, как создать регулярное выражение (я). Есть идеи?

Ответы [ 4 ]

4 голосов
/ 11 октября 2011

Запрос trin and is становится следующим регулярным выражением:

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

Другими словами, не используйте регулярные выражения для этого.

3 голосов
/ 11 октября 2011

Вероятно, не стоит делать это с помощью регулярного выражения. (Чистое, информатика) регулярное выражение «не в счет». Единственная «память», которую он имеет в любой момент - это состояние DFA. Чтобы сопоставить несколько слов в любом порядке без повторения, вам потребуется порядка 2 ^ n состояний. Так что, вероятно, действительно ужасное регулярное выражение.

(Кроме того: я упоминаю «чистые, компьютерные» регулярные выражения, потому что большинство реализаций на самом деле являются расширениями и позволяют вам выполнять нерегулярные вещи. сделай то, что ты хочешь сделать, менее безболезненно с помощью одного шаблона.)

Лучшим подходом было бы сохранить словарь (объект в JavaScript), который сопоставляет слова со счетчиками. Инициализируйте его под свой набор слов с соответствующими значениями для каждого. Вы можете использовать регулярное выражение для сопоставления слов, а затем для каждого найденного слова уменьшать значение соответствующей записи в словаре. Если в конце словаря содержатся значения, отличные от 0, или если где-то очень длинный путь, по которому вы пытаетесь преуменьшить значение (или уменьшить значение, которое не существует), значит, у вас есть неудачное совпадение.

1 голос
/ 11 октября 2011

Я совершенно не уверен, что получу вас прямо здесь, поэтому я просто опубликую свое предложение для него.

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 будет содержать количество уникальных совпаденийдля запроса.Первый цикл split просто гарантирует, что никакие «двойники» не учитываются, поскольку мы перезаписываем наш поисковый объект.Второй цикл проверяет наличие отдельных слов в целевой строке и использует изящную + для преобразования результата (либо true, либо false) в число, следовательно, +1 в совпадении или + 0.

0 голосов
/ 20 сентября 2012

Я искал решение этой проблемы, и ни одно из представленных здесь решений не было достаточно хорошим, поэтому я пришел к следующему:

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...