passing string as a condition of a method in ruby

380 views Asked by At

Is there a way to create a condition through string manipulation. here is the code where I attempted to pass a string as a condition into include? method.

"hello eveyone in the house".include?(%w('hello' 'world' 'new\ york'    'place').join(" || ").to_s)
3

There are 3 answers

4
spickermann On BEST ANSWER

An conditional as argument to include? is not possible, because include? accepts only a string argument.

But you can write something like this:

['hello', 'world', 'new york', 'place'].any? { |word|
  "hello everyone in the house".include?(word)
}

Or you could generate a regexp from your strings:

"hello eveyone in the house".match?(
  /#{['hello', 'world', 'new york', 'place'].join('|')}/
)
1
Eric Duminil On

Another possibility would to split the words and use set intersection :

sentence  = "hello everyone in the house"
whitelist = %w(hello world new-york place)

found_words = sentence.split & whitelist
p found_words        # => ["hello"]
p found_words.empty? # => false

WARNING : It only works if the whitelist doesn't contain any string with multiple words. e.g. new york in the original question.

For a more robust solution, see @spickermann's answer.

3
peter On

Did some benchmarking to test the speed and to my surprise the first solution of spickerman is the fastest by far in MRI Ruby 2.3.0 on a windows box, followed by intersection while my own solution with Regexp.union ends up last :(

require 'benchmark' 

s = "hello everyone in the house"
a = ['hello', 'world', 'new york', 'place']

N = 10_000

Benchmark.bmbm do |x| 
  x.report("Union         ") { N.times { s.match(Regexp.union(a)) }}
  x.report("Union and scan") { N.times { s.scan(Regexp.union(a)) }}
  x.report("Interpollation") { N.times { s.match(/#{a.join('|')}/)}}
  x.report("intersect     ") { N.times { s.split & a }}
  x.report("block         ") { N.times { a.any? { |word| s.include?(word)}}}
end 

Rehearsal --------------------------------------------------
Union            0.110000   0.000000   0.110000 (  0.116051)
Union and scan   0.124000   0.000000   0.124000 (  0.121038)
Interpollation   0.110000   0.000000   0.110000 (  0.105943)
intersect        0.015000   0.000000   0.015000 (  0.018456)
block            0.000000   0.000000   0.000000 (  0.001908)
----------------------------------------- total: 0.359000sec

                     user     system      total        real
Union            0.109000   0.000000   0.109000 (  0.111704)
Union and scan   0.125000   0.000000   0.125000 (  0.119122)
Interpollation   0.109000   0.000000   0.109000 (  0.105288)
intersect        0.016000   0.000000   0.016000 (  0.017283)
block            0.000000   0.000000   0.000000 (  0.001764)