LoginSignup
80
58

More than 5 years have passed since last update.

配列に複数の値のいずれかが含まれているか判定

Last updated at Posted at 2017-09-07

例えば、ある配列に2と5のいずれかが含まれている、のような条件を書きたい時ありませんか?そんな時、みなさんはどう書くでしょうか。

ary = [1, 3, 5, 6, 8]
if ary.include?(2) || ary.include?(5)
  # do something
end

ary.include?を2回も書くのはちょっとイケてない気がする……ので、いくつか解決策を考えました。他にもこんなやり方あるよ!というのがあればぜひコメントで教えてください!

Array#-

ary = [1, 3, 5, 6, 8]
#2, 5のいずれかが含まれる
list = [2, 5]
(list - ary).size < list.size

#2, 5の両方が含まれる
(list - ary).empty?

ただし、一致判定の方法がArray#include?==を使うのに対してArray#-eql?なので、配列の中身のオブジェクトの種類によっては注意が必要です。

参考:https://oshiete.goo.ne.jp/qa/7042610.html

Enumerable#any?

ary = [1, 3, 5, 6, 8]
# 2, 5のいずれかが含まれる
[2, 5].any? {|i| ary.include?(i)}

# 2, 5の両方が含まれる
[2, 5].all? {|i| ary.include?(i)}

# 2〜5のいずれかが含まれる
ary.any? {|i| i.between?(2, 5)}

最後の例は、配列の中身が4.1Rational(10, 3)でもtrueになってしまうので要注意です。

Enumerable#grep

配列の中身が文字列の場合はEnumerable#grepも。正規表現が使えるので、細かい条件とかいろいろ付けられそうです。

# ARGVに -h か --help が含まれればヘルプメッセージを出力
unless ARGV.grep(/\A(-h|--help)\z/).empty?
  puts help_message
end

Array#include?を再定義

いっそ引数を複数取れるようにしてしまえばスッキリですね!

module Include
  refine Array do
    # all: trueの場合
    #   listの値全てがselfに含まれているか判定
    # all: falseの場合
    #   listの値のいずれかがselfに含まれているか判定
    def include?(*list, all: true)
      method = all ? :all? : :any?
      list.__send__(method) {|i| super(i)}
    end
  end
end

using Include
ary = [1, 3, 5, 6, 8]
ary.include?(2, 5, all: false) #=> true
80
58
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
80
58