NeilS NeilS - 6 months ago 30
Ruby Question

What is the shortest/most idiomatic way of determining whether a variable is any one of a list of values?

This seems a ridiculously simple question to be asking, but what's the shortest/most idiomatic way of rewriting this in Ruby?

if variable == :a or variable == :b or variable == :c or variable == :d # etc.

I saw this solution:

if [:a, :b, :c, :d].include? variable

but this isn't always functionally equivalent - I believe
actually looks to see if the variable object is contained in the list; it doesn't take into account that the object may implement its own equality test with
def ==(other)

As observed by helpful commentators below, that explanation isn't correct.
does use
but it uses the
method of the items in the array. In my example, it's the symbols, rather than the
method of the variable. That explains why it's not equivalent to my first code example.

(Take, for example, Rails'
request.format == :html
may return true, but
will return false, as
is an instance of Mime::Type, not a symbol.)

The best I have so far is:

if [:a, :b, :c, :d].select {|f| variable == f}.any?

but it seems somewhat cumbersome to me. Does anyone have better suggestions?


Actually, #include? does use ==. The problem arises from the fact that if you do

[:a].include? foo

it checks :a == foo, not foo == :a. That is, it uses the == method defined on the objects in the Array, not the variable. Therefore you can use it so long as you make sure the objects in the array have a proper == method.

In cases where that won't work, you can simplify your statement by removing the select statement and passing the block directly to any:

if [:a, :b, :c, :d].any? {|f| variable == f}