ユーザーIDの&検索を作ろうとして悩んだのでまとめてみます。
複数の配列から重複を抽出する方法
前提として以下のような配列があったとします。
a = [1,2,3]
b = [1,2,3,4,5]
c = [1,3,5]
1: & で比較する
配列がいくつあるかがわかっていれば、やることは簡単で以下のようにすれば重複する値を取ることができます。
a & b & c
=> [1,3]
しかし、配列の数がわからなかったり 空の配列が含まれている と上記の方法は使えません。
→空配列はOKでした。誤解でした。
2: 複数の配列を一つにまとめて重複する値を抽出する
そこで試したのが複数の配列を一つにまとめて抽出するという方法です、Arrayクラスにメソッドを追加してみました。
class Array
def duplicate_values(*arrays)
self.flatten! # 多重配列を単純にする
self.sort! # 並べ替える
self.select.with_index{|e,i| e == self[i+1] } # 次の値と比較して同じなら抽出
end
end
> [a,b,c].duplicate_values
=> [1,3]
このやり方について詳しくは参考サイトの方をご覧になってください。
参考:
Ruby の配列で重複する値のみを取り出す
Rubyで配列から重複したモノ(要素)を抜き出す(Uniqの逆)
この方法では以下の問題点があり、今回の私の目的には使えませんでした。
- 配列が3つ以上あった場合にすべての配列に共通する値を抽出できない
- 配列同士の比較は行っていないので、一つの配列内に同じ値が複数あるなどの場合も抽出されてしまう
3: 配列の個数分だけ比較する
結局配列同士を比較しないとダメだよねということに気づいてやったのが次の方法です。
def duplicate_values
max = self.size
self.reverse_each.with_index do |e,i|
break if i == max-1 # N-1回比較
@dup_values = @dup_values ? @dup_values & self[i] : self[i] & e
end
@dup_values
end
> [a,b,c].duplicate_values
=> [1,3]
すべての配列で共通する値はこでれ取ることができました。
今回はとりあえず目的達成できましたが、なんだかもっといい感じに書けそうな気もします。
良いアイディアがあったらぜひ教えて下さい!
=> コメントでGOODアイディア頂きました!コメント欄の方もご覧ください。