从哈希数组中获取基于字符串的唯一元素

时间:2014-11-17 14:39:46

标签: ruby-on-rails ruby

我有一系列哈希:

[{: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-aaa90-bbb45-hhh32-kkk。 我希望根据值a的ID来获取数组的唯一元素:

[{:a => "63-aaa",:b =>1}, {:a => "90-bbb",:b => 89}, {:a => "45-hhh", :b => 44}, {:a => "32-kkk", :b => 67}]

2 个答案:

答案 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 } 。如果hf都有密钥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}]]

然后使用您喜欢的任何条件从四个数组中的每一个中选择一个哈希值。