Вот мой шанс:
def match_freq(exprs, strings)
rs, ss, f = exprs.split.map{|x|Regexp.new(x)}, strings.split, {}
rs.each{|r| ss.each{|s| f[r] = f[r] ? f[r]+1 : 1 if s=~r}}
[f.values.inject(0){|a,x|a+x}, f, f.size]
end
list1 = "fred sam sandy jack sue bill"
str = "and so sammy went with jack to see fred and freddie"
x = match_freq(list1, str)
x # => [4, {/sam/=>1, /fred/=>2, /jack/=>1}, 3]
Вывод «match_freq» - это массив ваших выходных элементов (a, b, c).Сам алгоритм имеет вид O(n*m)
, где n
- это количество элементов в списке list1, а m
- это размер входной строки, я не думаю, что вы можете сделать это лучше (в терминах big-oh).Но есть меньшие оптимизации, которые могут окупиться, как сохранение отдельного счетчика для общего числа совпадений, а не вычисление его впоследствии.Это был только мой быстрый взлом.
Вы можете извлечь только соответствующие слова из вывода следующим образом:
matches = x[1].keys.map{|x|x.source}.join(" ") # => "sam fred jack"
Обратите внимание, что порядок не будет сохранен обязательно, если этоважно, чтобы вы вели отдельный список порядка, в котором они были найдены.