例えば、ある配列に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.1
やRational(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