Here is my picture:
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
The output of match_freq is an array of your output elements (a, b, c). The algorithm itself is O(n*m) , where n is the number of elements in the list1, and m is the size of the input string, I don’t think you can do better than this (in big-oh terms). But there are less optimizations that can pay off, for example, keeping a separate counter for the total number of matches, rather than calculating it later. It was just my quick hack.
You can output only the corresponding words from the output as follows:
matches = x[1].keys.map{|x|x.source}.join(" ") # => "sam fred jack"
Please note that the order will not be saved necessarily, if it is important, you will need to keep a separate list of the order in which they were found.
source share