2015-08-25 3 views
0

Есть ли способ/камень для создания регулярных выражений с некоторыми базовыми параметрами поиска.Создать регулярное выражение из массива поисковых запросов ruby ​​

например.

Search = ["\"German Shepherd\"","Collie","poodle", "Miniature Schnauzer"] 

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

"Немецкая овчарка" - точно ИЛИ "Колли" ИЛИ "пудель" ИЛИ "миниатюрной" И «Шнауцер»

В этом случае примерно следующее:

/German\ Shepherd|Collie|poodle|(?=.*Miniature)(?=.*Schnauzer).+/i 

(Открыт для предложений лучших способов сделать последний бит ...)

+0

Другое кроме того, что вы хотите разделить Миниатюрный и шнауцеры, но не немецкий и пастух что-то, как это будет работать. '/ # {search.join ('|')}/i', но с учетом дополнительных критериев методология станет немного сложнее. Можете ли вы добавить какие-либо другие «особые случаи», которым может потребоваться дополнительная обработка? – engineersmnky

+0

Да, я добрался так далеко. Причина, по которой я прошу, заключается в том, что я понял, что неправильно обрабатывает «Миниатюрный шнауцер» ... – Carpela

+0

Другим специальным случаем были бы исключения. то есть дополнительный массив исключений, который, если они присутствуют, будет упускать совпадение, – Carpela

ответ

2

Если я правильно понял вопрос, здесь вы идете:

regexps = ["\"German Shepherd\"","Collie","poodle", "Miniature Schnauzer"] 

# those in quotes 
greedy = regexps.select { |re| re =~ /\A['"].*['"]\z/ } # c'"mon, parser 
# the rest unquoted 
non_greedy = (regexps - greedy).map(&:split).flatten 

# concatenating...      ⇓⇓⇓ get rid of quotes  
all = Regexp.union(non_greedy + greedy.map { |re| re[1...-1] }) 
#⇒ /Collie|poodle|Miniature|Schnauzer|German\ Shepherd/ 

UPD

Наконец-то я получил то, что должно быть сделано с Miniature Schnauzer (см. Комментарий ниже для дальнейшего объяснения.) Тем не менее, эти слова должны быть перестановлены, а j oined с нежадным .*?:

non_greedy = (regexps - greedy).map(&:split).map do |re| 
    # single word? YES : NO, permute and join 
    re.length < 2 ? re : re.permutation.map { |p| Regexp.new p.join('.*?') }  
end.flatten 
all = Regexp.union(non_greedy + greedy.map { |re| re[1...-1] }) 

#=> /Collie|poodle|(?-mix:Miniature.*?Schnauzer)|(?-mix:Schnauzer.*?Miniature)|German\ Shepherd/ 
+0

Что делает бит миниатюрного шнауцера, это добавить набор слов, которые должны быть найдены вместе, хотя и не обязательно в этой точной форме, поэтому «Миниатюрный черный шнауцер» вернется в качестве соответствия, как «Шнауцер - миниатюра» – Carpela

+0

Получил его. См. Обновление. – mudasobwa

+0

Спасибо, это действительно хорошо. (? =. * Миниатюра) (? =. * Шнауцер). + Я думаю, это немного более изящная форма (+.) - все это, а остальные выбирают два слова. Особенно, если есть более двух слов. Просто попытайтесь разобраться, как это сделать ... – Carpela