ここに、これらと@ Pascalの方法をベンチマーク比較した2つのソリューションがあります。
使用は
require 'set'
def multi_set(arr)
s1 = Set.new
arr.each_with_object(Set.new) { |e, smulti| smulti.add(e) unless s1.add?(e) }.to_a
end
arr = ["mike", "mike", "mike", "john", "john", "peter", "clark"]
multi(arr)
#=> ["mike", "john"]
s1
を設定arr
の全ての別個の要素を含むように構築されています。 s1.add?(e)
は、が既に含まれている場合は、e
がsmulti
に追加されている場合は、smulti
にその要素が含まれていない場合、nil
を返します。 (Set#add?を参照してください)smulti
がメソッドによって返されます。
使用Array#difference
Array#difference
は、私はRubyのコアにproposedを追加しました方法です。私の答えhereも参照してください。もちろん
class Array
def difference(other)
h = other.each_with_object(Hash.new(0)) { |e,h| h[e] += 1 }
reject { |e| h[e] > 0 && h[e] -= 1 }
end
end
def multi_difference(arr)
arr.difference(arr.uniq).uniq
end
ベンチマーク
def more_than_once(arr)
counts = Hash.new { |hash, key| hash[key] = 0 }
arr.each do |item|
counts[item] += 1
end
counts.select do |_, count|
count > 1
end.keys
end
require 'fruity'
items = 30_000_000
arr = items.times.map { rand 10_000_000 }
compare do
Pascal { more_than_once(arr) }
Set { multi_set(arr) }
Difference { multi_difference(arr) }
end
Running each test once. Test will take about 4 minutes.
Pascal is faster than Set by 19.999999999999996% ± 10.0%
Set is faster than Difference by 30.000000000000004% ± 10.0%
、difference
、Rubyのコアの一部であれば、Cにおいて符号化され、最適化されるであろう。
ブレインストームのビットですが、これらの値をハッシュテーブルに入力した場合、競合する場合は重複していると見なされますか? – DrSatan1
ブレインストーム継続:1,000,000,000エントリの想定32ビットハッシュでは、最大4ギガバイトのテーブルが必要です。これは、各ビットが占有されたハッシュを表すビットセットを使用することによって、116メガバイトまで煮沸することができる。このアプローチでは、潜在的な重複を除外するためにデータを2回通過する必要があります。 –
あなたのユースケースで受け入れられるランタイムは何ですか? 小さい配列の比較を理解しています。 これは、各配列に他の配列に表示されていない項目が含まれていると確信している場合にのみ同じ結果を返します。 –