I'm not sure the benefits of either approach, you would need to do the empirical study yourself, but there are a couple of ways.
Instead of looping over the set of keys and searching the string (200+) times, you can just search the string once with a rather large regular expression.
Code:
str = "This string has twice the number of ints as longs (int)"
keys = ["int", "long", "double"]
found = Hash.new(false) # unbound indexes return false, not nil
str.scan(/#{keys.join('|')}/) { |x| found[x] = true }
# => {"int"=>true, "long"=>true}
Realize that this matches words within words (take note that it found
long from
longs).
Or you can do the loop the way you designed
Code:
str = "This string has twice the number of ints as longs (int)"
keys = ["int", "long", "double"]
found = Hash.new(false) # unbound indexes return false, not nil
keys.each do |key|
found[key] = /#{key}/.match(str) ? true : false
end
# => {"int"=>true, "double"=>false, "long"=>true}
Again, with the word within words problem but notice also the subtle difference in the resulting hash. The second method above explicitly sets a value for
all keys and not just the ones found. This may or may not make your post processing any harder.
With regard to the word within words dilemma (which you might have considered already), you can provide extra search criteria to the regular expression to limit by word or space boundaries. Doing so necessarily changes the data (and possibly its format) returned from the match/scan call.
Read up on the
String#scan,
Regexp#match, and
Regexp class for more information.