2012-01-10 2 views
4

Я хотел бы найти все совпадения заданных строк (разделенных пробелами) в строке. (Например, работает окно поиска iTunes).regex javascript - соответствует нескольким условиям поиска, игнорируя их порядок.

Это, например, как «аб де» и «де аб» возвращает истину на «ABCDE» (также «Ьс еа» или любой заказ должен вернуть истинный)

Если я заменю пустое место на wild card, «ab * de» вернет true на «abcde», но не «de * ab». [Я использую *, а не синтаксис Regex только для этого объяснения]

Я не мог найти для этого чистого решения Regex. Единственное решение, о котором я мог думать, это слияние поискового термина и запуск нескольких регулярных выражений.

Можно ли найти чисто выражение регулярного выражения, которое будет охватывать все эти параметры?

+1

* Почему? * На самом деле это не то, что было предложено регулярным выражением, так почему вы пытаетесь перевернуть его в регулярное выражение? Просто выполните поиск по каждой из строк. – Amber

+0

Почему 'ab * de' соответствует' abcd'? Где 'e'? Кроме того, если шаблон 'ad de' также действителен для данной фразы' ad hominem' (поскольку найдено 'ad')? В чем смысл астерики: должны ли быть сопоставлены все предшествующие символы без пробелов или только предыдущий символ? –

+0

@Amber: Я просто думал, что чистое Regex будет быстрее. Я использую этот поиск для фильтрации результатов на лету для выпадающего списка. Так что это должно быть быстро. – Ranch

ответ

3

Попробуйте это:

var str = "your string"; 
str = str.split(" "); 
for(var i = 0 ; i < str.length ; i++){ 
    // your regexp match 
} 
+0

Ну, я спрашивал, есть ли чистое решение Regex ... догадка не – Ranch

+0

'i' и' c' не были объявлены. Что в стороне, почему вы проверяете 'c' на массив? Split всегда возвращает массив, содержащий один элемент, если ни один символ не найден, или нулевые элементы, если строка пуста. –

+0

@RobW Вы правы. Черт, совершенно не заметил ... Отредактировал сейчас. –

4

Я уверен, что вы могли бы придумать регулярное выражение, чтобы делать то, что вы хотите, но это не может быть наиболее эффективным подходом.

Например, регулярное выражение шаблон (?=.*bc)(?=.*e)(?=.*a) будет соответствовать любой строке, которая содержит bc, e, иa.

var isMatch = 'abcde'.match(/(?=.*bc)(?=.*e)(?=.*a)/) != null; // equals true 

var isMatch = 'bcde'.match(/(?=.*bc)(?=.*e)(?=.*a)/) != null; // equals false 

Вы могли бы написать функцию, чтобы динамически создавать выражения на основе ваших поисковых терминов, но является ли это лучший способ добиться того, что вы делаете, это другой вопрос.

-1

Я думаю, что вы можете лаять неправильное дерево с RegEx. Что вы может хотите посмотреть на Levenshtein distance двух входных строк.

Внедрение Javascript here и пример использования here.

+0

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

3

Чередование порядково нечувствительны:

"abcde".match(/(ab|de)/g); // => ['ab', 'de'] 
"abcde".match(/(de|ab)/g); // => ['ab', 'de'] 

Так что если у вас есть список слов, чтобы соответствовать вы можете построить регулярное выражение с чередованием на лету, как так:

function regexForWordList(words) { 
    return new RegExp('(' + words.join('|') + ')', 'g'); 
} 
'abcde'.match(['a', 'e']); // => ['a', 'e'] 
+0

Это называется * чередование *. А * условный * более сложный ([ref] (http://www.regular-expressions.info/conditional.html)). –

+0

это хороший подход, но он вернёт true, если любое из слов ('ab' OR 'de') будет в строке соответствия. Я хочу, чтобы он возвращал true только в том случае, если были найдены «ab» AND «de». – Ranch

+0

Затем проверьте, найдены ли «ab» и «de» в массиве совпадений? – imme

1

Я предполагаю, что вы являются совпадающие слова или части слов. Вы хотите, чтобы условия поиска, разделенные пробелами, ограничивали результаты поиска, и кажется, что вы намерены возвращать только те записи, которые содержат все слова, которые пользователь предоставляет. И вы намереваетесь подстановочный знак *, чтобы стоять за 0 или более символов в соответствующем слове.

Например, если пользователь ищет в словах TERM1 term2, вы намерены возвращать только те элементы, которые имеют оба словаterm1иterm2.Если пользователь ищет слово термин *, он будет соответствовать любому слову, начинающемуся с term.

Существуют подходящие регулярные выражения, которые эквивалентны этому языку поиска и могут быть сгенерированы из него.

Простой пример: слово term, может быть указано в регулярном выражении путем преобразования в \bterm\b. Но два или более слова, которые должны совпадать в любом порядке, требуют утверждений о взглядах. Используя расширенный синтаксис, что эквивалентно регулярное выражение:

(?= .* \b term1 \b) 
(?= .* \b term2 \b) 

Звездочка подстановочные можно утверждать, в регулярных выражениях с классом персонажа, затем звездочкой. Класс символов определяет, какие буквы вы считаете частью слова. Например, вы можете обнаружить, что [A-Za-z0-9]* подходит для счета.

Короче говоря, вы могли бы быть удовлетворены, если преобразовать выражение, как:

foo ba* quux 

к:

(?= .* \b foo   \b) 
(?= .* \b ba[A-Za-z0-9]* \b) 
(?= .* \b quux   \b) 

То есть простой вопрос поиска и замены. Но не будьте осторожны, чтобы дезинфицировать строку ввода, чтобы избежать атак инъекционного пути удаления знаков препинания и т.д.

2

Это скрипт, который я использую - это также работает с одиночным searchStrings слова

var what="test string with search cool word"; 
var searchString="search word"; 
var search = new RegExp(searchString, "gi"); // one-word searching 

// multiple search words 
if(searchString.indexOf(' ') != -1) { 

    search=""; 
    var words=searchString.split(" "); 

    for(var i = 0; i < words.length; i++) { 

     search+="(?=.*" + words[i] + ")"; 

    } 

    search = new RegExp(search + ".+", "gi"); 

} 

if(search.test(what)) { 

    // found 

} else { 

    // notfound 

} 
4

Возвращение true, когда все части (разделенные на , или ' ') searchString встречаются в тексте. В противном случае возвращается false.

filter(text, searchString) { 
    const regexStr = '(?=.*' + searchString.split(/\,|\s/).join(')(?=.*') + ')'; 
    const searchRegEx = new RegExp(regexStr, 'gi'); 
    return text.match(searchRegEx) !== null; 
} 
Смежные вопросы