25

ハッシュの配列があり、そこから一意の値が必要です。電話をかけArray.uniqても、私が期待するものは得られません。

a = [{:a => 1},{:a => 2}, {:a => 1}]
a.uniq # => [{:a => 1}, {:a => 2}, {:a => 1}]

私が期待したところ:

[{:a => 1}, {:a => 2}]

ネットで検索してみたところ、満足できる解決策は思いつきませんでした。人々は再定義Hash.eql?を推奨しました、そしてそれがクエリHash.hashしているものだからです。Array.uniq

編集:私が現実の世界でこれに遭遇したところ、ハッシュは少し複雑でした。それらは、複数のフィールドを持つ解析されたJSONの結果であり、その一部の値もハッシュでした。一意の値を除外したい結果の配列がありました。

Hash.eql?再定義とHash.hashソリューションは好きではありませんHash。グローバルに再定義するか、配列のエントリごとに再定義する必要があるためです。各エントリの定義を変更するのはHash面倒です。特に、各エントリ内にネストされたハッシュがある場合があるためです。

Hash特に一時的に行われた場合、グローバルに変化する可能性があります。古い定義を保存して復元することをラップした別のクラスまたはヘルパー関数を作成したいのですが、これにより、実際に必要とされるよりも複雑になると思います。

を使用injectすることは、を再定義するための良い代替手段のようHashです。

4

8 に答える 8

27

電話で欲しいものが手に入るinject

a = [{:a => 1},{:a => 2}, {:a => 1}]
a.inject([]) { |result,h| result << h unless result.include?(h); result }

これは戻ります:

[{:a=>1}, {:a=>2}]
于 2008-10-08T01:44:15.353 に答える
18

Ruby 1.8.7+は、期待どおりの結果を返します。

[{:a=>1}, {:a=>2}, {:a=>1}].uniq
#=> [{:a=>1}, {:a=>2}] 
于 2011-04-11T19:27:57.213 に答える
3

使用できます(Ruby 1.9.3でテスト済み)、

[{a: 1},{a: 2},{a:1}].uniq => [{a:1},{a: 2}]
[{a: 1,b: 2},{a: 2, b: 2},{a: 1, b: 3}].uniq_by {|v| v[:a]} => [{a: 1,b: 2},{a: 2, b: 2}]
于 2015-01-05T08:49:26.047 に答える
3

ハッシュが常に単一のキーと値のペアであると仮定すると、これは機能します。

a.map {|h| h.to_a[0]}.uniq.map {|k,v| {k => v}}

Hash.to_a はキーと値の配列の配列を作成するため、最初のマップは次のようになります。

[[:a, 1], [:a, 2], [:a, 1]]

uniq on Arrays は、あなたが望むことを行い、次のことを行います:

[[:a, 1], [:a, 2]]

そして、2 番目のマップはそれらを再びハッシュとしてまとめます。

于 2008-10-08T16:35:11.250 に答える
0

あなたが与える答えは、ここで議論されているものと似ています。配列に表示されるハッシュのメソッドhashとメソッドをオーバーライドし、正しく動作させます。eql?uniq

于 2008-10-08T04:52:36.330 に答える
0

配列のパイプ メソッド (1.8.6 以降で使用可能) は集合和集合 (配列を返す) を実行するため、次の方法で任意の配列の一意の要素を取得することができますa

[] | a

于 2012-11-07T16:49:27.273 に答える