102
78

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

複数の配列を比較し重複する値を取る

Last updated at Posted at 2015-10-19

ユーザーIDの&検索を作ろうとして悩んだのでまとめてみます。

複数の配列から重複を抽出する方法

前提として以下のような配列があったとします。

a = [1,2,3]
b = [1,2,3,4,5]
c = [1,3,5]

1: & で比較する

配列がいくつあるかがわかっていれば、やることは簡単で以下のようにすれば重複する値を取ることができます。

a & b & c
=> [1,3]

参考:2つの配列から重複を省いたり、重複を得たり

しかし、配列の数がわからなかったり 空の配列が含まれている と上記の方法は使えません。
→空配列は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アイディア頂きました!コメント欄の方もご覧ください。

102
78
5

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
102
78

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?