60

Is there a better way to write this:

if myarray.include? 'val1' ||
   myarray.include? 'val2' ||
   myarray.include? 'val3' ||
   myarray.include? 'val4'
Hopstream
  • 6,391
  • 11
  • 50
  • 81

2 Answers2

109

Using set intersections (Array#:&):

(myarray & ["val1", "val2", "val3", "val4"]).present?

You can also loop (any? will stop at the first occurrence):

myarray.any? { |x| ["val1", "val2", "val3", "val4"].include?(x) }

That's ok for small arrays, in the general case you better have O(1) predicates:

values = ["val1", "val2", "val3", "val4"].to_set
myarray.any? { |x| values.include?(x) }

With Ruby >= 2.1, use Set#intersect:

myarray.to_set.intersect?(values.to_set)
tokland
  • 66,169
  • 13
  • 144
  • 170
  • 1
    is there something simpler to read like this `if myarray.include? ['val1', 'val2', 'val3']` If not, then I guess your answer seems best. – Hopstream Nov 06 '11 at 10:16
  • @Hopstream, added another implementation with any? – tokland Nov 06 '11 at 10:30
  • 2
    why use the negative form ? why not just use `(self & other).any?` instead of `!(self & other).empty?` – m_x Nov 06 '11 at 11:04
  • 2
    @m_x: good point, usually _any?_ is used with a block, but it makes perfect sense without. Edited. [edit] but what if nil/false are values in the arrays? any will fail... – tokland Nov 06 '11 at 11:13
  • 1
    interesting. looking at the sources of `any?` and `empty?`, from a performance point of view, you're indeed right to use the negative form (`empty?` just checks the length of the C array, while `any?` involves a more complex process because of the _absent_ block). I learned something today. – m_x Nov 06 '11 at 11:20
  • @m_x. mee too :-) I'll put !empty again. – tokland Nov 06 '11 at 11:23
  • ooooh, right, did not think about `false`. Two lessons in two minutes ! – m_x Nov 06 '11 at 11:24
  • I guess I got excited to the use the cleaner .any? form too soon :) -- back to using the .empty – Hopstream Nov 06 '11 at 11:28
  • Just curious... would it be possible to use a switch case here to accomplish this also? – Hopstream Nov 06 '11 at 11:32
  • the !empty is easily solved, adding a present? or non_empty? method to arrays. I do in my projects, I don't like negate expressions either. Why do you want a switch case here? I don't see how it fits... – tokland Nov 06 '11 at 11:46
  • hey, let's monkey-patch `Array` : `def any_value? ; !self.empty? ; end`. much cleaner. – m_x Nov 06 '11 at 11:51
  • be careful, `present?` is already added to `Array` in rails ! Third lesson today... – m_x Nov 06 '11 at 11:53
  • Why not just use `.nil?` after grabbing the intersection? I think that's fairly readable. – Sergio Sep 29 '14 at 14:36
5

Create your own reusable method:

class String
  def include_any?(array)
    array.any? {|i| self.include? i}
  end
end

Usage

"a string with many words".include_any?(["a", "string"])
Jeremy Lynch
  • 6,780
  • 3
  • 52
  • 63