我有一系列哈希:
[{:a => "63-aaa",:b =>1}, {:a => "90-bbb",:b => 89}, {:a => "63-aaa", :b => 1},{:a => "45-hhh", :b => 44}, {:a => "32-kkk", :b => 67}, {: => "90-bbb", :b => 89}]
a
键的值为63-aaa
,90-bbb
,45-hhh
和32-kkk
。
我希望根据值a
的ID来获取数组的唯一元素:
[{:a => "63-aaa",:b =>1}, {:a => "90-bbb",:b => 89}, {:a => "45-hhh", :b => 44}, {:a => "32-kkk", :b => 67}]
答案 0 :(得分:8)
在这种情况下,你可以将一个块传递给Array#uniq
:
arr.uniq { |hash| hash[:a] }
答案 1 :(得分:2)
您似乎并不关心每组重复项中的哪一项。带有块的Array#uniq
是专门为此而构建的。它将保持索引最小的那个。如果您想要索引最大的索引,只需在Array#reverse
之前和之后应用uniq
。
但是,如果您希望在每个哈希中使用其他信息来确定要保留哪个信息,则可以使用带有块的Hash#update(aka merge!
)形式来执行此操作:
arr = [{:a=>"63-aaa", :b=> 1}, {:a=>"90-bbb", :b=>89}, {:a=>"63-aaa", :b=>22},
{:a=>"45-hhh", :b=>44}, {:a=>"32-kkk", :b=>67}, {:a=>"90-bbb", :b=>14}]
arr.each_with_object({}) do |g,h|
h.update({ g[:a]=>g }) { |k,oh,nh| <code to return oh or nh> }
end.values
例如,假设您要保留h
最大的哈希h[:b]
:
arr.each_with_object({}) do |g,h|
h.update({ g[:a]=>g }) { |k,oh,nh| nh[:b] > oh[:b] ? nh : oh }
end.values
#=> [{:a=>"63-aaa", :b=>22}, {:a=>"90-bbb", :b=>89},
# {:a=>"45-hhh", :b=>44}, {:a=>"32-kkk", :b=>67}]
我创建了一个空哈希(块变量h
),然后针对g
中的每个哈希arr
,使用哈希h
更新f = { g[:a]=>g }
。如果h
和f
都有密钥g[:a]
,那么阻止
{ |k,oh,nh| (nh[:b] > oh[:b]) ? nh : oh }
被要求确定g[:a]
中密钥h
的值(即要保留的两个哈希中的哪一个)。块变量是:
k = g[:a]
oh = h[g[:a]]
nh = g
(请注意,块中未使用k
,因此我们可能会将块变量写为|_,oh,nh|
。)
each_with_object
返回
h = {"63-aaa"=>{:a=>"63-aaa", :b=>22}, "90-bbb"=>{:a=>"90-bbb", :b=>89},
"45-hhh"=>{:a=>"45-hhh", :b=>44}, "32-kkk"=>{:a=>"32-kkk", :b=>67}}
所以我们只需要提取值:
h.values
#=> [{:a=>"63-aaa", :b=>22}, {:a=>"90-bbb", :b=>89},
# {:a=>"45-hhh", :b=>44}, {:a=>"32-kkk", :b=>67}]
另一种方法是先执行:
arr.group_by { |h| h[:a] }.values
#=> [[{:a=>"63-aaa", :b=> 1}, {:a=>"63-aaa", :b=>22}],
# [{:a=>"90-bbb", :b=>89}, {:a=>"90-bbb", :b=>14}],
# [{:a=>"45-hhh", :b=>44}],
# [{:a=>"32-kkk", :b=>67}]]
然后使用您喜欢的任何条件从四个数组中的每一个中选择一个哈希值。