🐈

[Rails]とある配列の要素が他の配列に含まれているかを確かめようとしたら詰まったので、私が実際に行った対処方法の覚書

2022/10/16に公開
2

※本記事は初学者が業務中に詰まったところをクリアした方法の覚書です。調べてもいい方法が出てこなかったので(自身のためにも)記事として残します。もっと良い方法を知っていたら教えてください。


Railsである要素が配列に含まれているかを確かめる方法として、パッと思いつくのはinclude?だと思われる。

ところが、とある配列の要素が別の配列に含まれているかを確かめるためにinclude?を使っても望んだ応答を得られないことがある。
↓例

A = %w(apple)
B = %w(apple orange banana)
B.include?(A)

これに対する応答はfalseとなる。

なんでやapple含まれてるやろ
って言いたくなるところだが、上の例は厳密には

A = ['apple']
B = ['apple', 'orange', 'banana']

となる。

Bに['apple']は含まれていないのである。したがってfalseが返ってきて正しいのだ。

では、trueを得るためにはどうしたらいいのか。
Aから'apple'を取り出したらいいのだ。

そんなわけで、先ほどの例を少し変更する。

A = %w(apple)
B = %w(apple orange banana)
a = A.slice(0)
B.include?(a)

これでtrueが返ってきて、Bにappleが含まれていることがわかります。

sliceについては以下を確認してください。
https://docs.ruby-lang.org/ja/latest/method/Array/i/slice.html


ここからは余談

A = %w(apple orange banana)
B = %w(apple orange banana)

のときに、Aの配列の要素全てがBに含まれていることを確かめたければ

(A - B).blank?

とでもすればtrueが得られるはずだ。
こちらuniversato様からご指摘を受けて修正しました(2022/10/18)


本記事について、Discussionにてuniversato様が非常に良いナレッジを下さりました。
ありがとうございますmm
こちらも併せてご閲覧いただけると幸いです。

Discussion

ピン留めされたアイテム
universatouniversato

sliceって実は[]と同等の機能で、
A.slice(0)よりもA[0]の方が良さそうです。
sliceは馴染みが薄い人が多いでしょうし、[]の方が短くてスタイリッシュなので!

それから、最後の余談について
Aの配列の要素全てがBに含まれていることを確かめるときは
B - AではなくA - Bの形を利用した方がいいと思います。

B = %w(apple orange banana)

A = %w(apple orange banana)
p (B - A).blank? # true

A = %w(apple orange)
p (B - A).blank? # false

どちらもAの配列の要素全てがBに含まれますが、
判定が異なっており、B - Aだとちゃんと判定できないです。

B - Aですと「要素数が同じでAに重複がない」という条件が必要になったりするのが良くないかと。

なお、全要素の判定では、setライブラリのSetに変換してSet#subset?を使う書き方が読みやすいかもと思いました。

参考:

あやつきあやつき

コメントありがとうございます。

sliceと同じことが[]でできるとは、知らなかったです!

余談の方ですが

「要素数が同じでAに重複がない」という条件が必要になったりする

この意図で書いていました。。。(余談だからと雑な文章を書いてしまってすみませんmm)
Setいいですね〜全要素判定がする際には使ってみようと思います!

勉強になりました!ありがとうございますmm