46

In Ruby, how would I return true if a string is not in an array of options?

# pseudo code
do_this if current_subdomain not_in ["www", "blog", "foo", "bar"]

...or do you know of a better way to write this?

1

5 Answers 5

75
do_this unless  ["www", "blog", "foo", "bar"].include?(current_subdomain)

or

do_this if not ["www", "blog", "foo", "bar"].include?(current_subdomain)

I'm using the Array#include? method.

However using unless is a fairly big ruby idiom.

Sign up to request clarification or add additional context in comments.

1 Comment

do_this if !["www", "blog", "foo", "bar"].include?(current_subdomain) works. For complex conditions, example one: && ! example two: and not.
13

You can try exclude? method instead of include?

Example:

do_this if ["www", "blog", "foo", "bar"].exclude?(current_subdomain)

Hope this help...Thanks

Edited: This function is applicable only for Rails (ActiveSupport), not native Ruby.

2 Comments

exclude? only comes from ActiveSupport library. Not officially supported in core Ruby.
This function (exclude) is not available in Ruby as of v2.5. You will get a NoMethodError.
4

Besides using an array, you can also do this:

case current_subdomain
when 'www', 'blog', 'foo', 'bar'; do that
else do this
end

This is actually much faster:

require 'benchmark'
n = 1000000

def answer1 current_subdomain
  case current_subdomain
  when 'www', 'blog', 'foo', 'bar'
  else nil
  end
end

def answer2 current_subdomain
  nil unless  ["www", "blog", "foo", "bar"].include?(current_subdomain)
end

Benchmark.bmbm do |b|
  b.report('answer1'){n.times{answer1('bar')}}
  b.report('answer2'){n.times{answer2('bar')}}
end

Rehearsal -------------------------------------------
answer1   0.290000   0.000000   0.290000 (  0.286367)
answer2   1.170000   0.000000   1.170000 (  1.175492)
---------------------------------- total: 1.460000sec

              user     system      total        real
answer1   0.290000   0.000000   0.290000 (  0.282610)
answer2   1.180000   0.000000   1.180000 (  1.186130)


Benchmark.bmbm do |b|
  b.report('answer1'){n.times{answer1('hello')}}
  b.report('answer2'){n.times{answer2('hello')}}
end

Rehearsal -------------------------------------------
answer1   0.250000   0.000000   0.250000 (  0.252618)
answer2   1.100000   0.000000   1.100000 (  1.091571)
---------------------------------- total: 1.350000sec

              user     system      total        real
answer1   0.250000   0.000000   0.250000 (  0.251833)
answer2   1.090000   0.000000   1.090000 (  1.090418)

1 Comment

In answer2, defining the array ["www", "blog", "foo", "bar"] as a constant outside the method is faster, but still slower than using when.
3
do this if not ["www", "blog", "foo", "bar"].include?(current_subdomain)

or you can use grep

>> d=["www", "blog", "foo", "bar"]
>> d.grep(/^foo$/)
=> ["foo"]
>> d.grep(/abc/)
=> []

Comments

2

I find this approach most readable !'foo'.in?(['bar', 'baz'])

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.