3

要素を繰り返すセットの交差と和集合を Ruby で取得するにはどうすればよいですか。

# given the sets
a = ["A", "B", "B", "C", "D", "D"]
b = ["B", "C", "D", "D", "D", "E"]

# A union function that adds repetitions
union(a, b)
=> ["A", "B", "B", "C", "D", "D", "D", "E"]

# An intersection function that adds repetitions
intersection(a, b)
=> ["B", "C", "D", "D"]

ドキュメントに書かれているように、演算子&と演算子は繰り返しと重複を無視するようです。|

# union without duplicates
a | b
=> ["A", "B", "C", "D", "E"]

# intersections without duplicates
a & b
=> ["B", "C", "D"]
4

2 に答える 2

1

Cary Swoveland の answerに基づいて構築すると、一時的なハッシュを作成して、各配列内の各メンバーの出現回数をカウントできます (引数の数を一般化しました)。

def multiplicities(*arrays)
  m = Hash.new { |h, k| h[k] = Array.new(arrays.size, 0) }
  arrays.each_with_index { |ary, idx| ary.each { |x| m[x][idx] += 1 } }
  m
end

multiplicities(a, b)
#=> {"A"=>[1, 0], "B"=>[2, 1], "C"=>[1, 1], "D"=>[2, 3], "E"=>[0, 1]}

実装unionintersection簡単です:

def union(*arrays)
  multiplicities(*arrays).flat_map { |x, m| Array.new(m.max, x) }
end

def intersection(*arrays)
  multiplicities(*arrays).flat_map { |x, m| Array.new(m.min, x) }
end

union(a, b)        #=> ["A", "B", "B", "C", "D", "D", "D", "E"]
intersection(a, b) #=> ["B", "C", "D", "D"]

このアプローチでは、各配列を 1 回だけトラバースする必要があります。

于 2016-06-15T13:32:28.590 に答える