简体   繁体   English

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

[英]Get unique element on basis of string from array of hash

I have an array of hashes: 我有一系列哈希:

[{: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 key has value 63-aaa , 90-bbb , 45-hhh and 32-kkk . a钥匙的价值是63-aaa90-bbb45-hhh32-kkk I want to get the unique elements of the array on the basis of ids of values of a like: 我想要得到的值的ID的基础上,数组的独特元素a样:

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

在这种情况下,您可以将块传递给Array#uniq

arr.uniq { |hash| hash[:a] }

You don't appear to care which one of each set of duplicates is kept. 您似乎并不关心保留每组重复项中的哪一项。 Array#uniq , with a block, is purpose-built for that. 带有块的Array#uniq是专门为此而构建的。 It will keep the one with the smallest index. 它将保持索引最小的那个。 If you want the one with the largest index, just apply Array#reverse before and after uniq . 如果你想要索引最大的那个,只需在uniq之前和之后应用Array#reverse

If, however, you wanted to use other information in each hash to determine which one to keep, you could do that by using the form of Hash#update (aka merge! ) that takes a block: 但是,如果您想在每个哈希中使用其他信息来确定要保留哪个信息,则可以使用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

Suppose, for example, you want to keep the hash h for which h[:b] is largest: 例如,假设您要保留h[:b]最大的哈希值h

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}]

I have created an empty hash (block variable h ), and then for each hash g in arr , update h with the hash f = { g[:a]=>g } . 我创建了一个空哈希(块变量h ),然后对于arr每个哈希g ,使用哈希值f = { g[:a]=>g }更新h If both h and f have the key g[:a] , the block 如果hf都有密钥g[:a] ,则为块

{ |k,oh,nh| (nh[:b] > oh[:b]) ? nh : oh  }

is called upon to determine the value of the key g[:a] in h (that is, which of the two hashes to keep). 被要求确定h中的键g[:a]的值(即,要保留的两个哈希值中的哪一个)。 The block variables are: 块变量是:

k  = g[:a]
oh = h[g[:a]]
nh = g

(Note that k is not used in the block, so we might write the block variables as |_,oh,nh| .) (注意块中没有使用k ,所以我们可以将块变量写成|_,oh,nh| 。)

each_with_object returns 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}}

so we merely have to extract the values: 所以我们只需要提取值:

h.values
  #=> [{:a=>"63-aaa", :b=>22}, {:a=>"90-bbb", :b=>89},
  #    {:a=>"45-hhh", :b=>44}, {:a=>"32-kkk", :b=>67}]

Another way is to first execute: 另一种方法是先执行:

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}]]

and then use whatever criteria you like to select one hash from each of the four arrays. 然后使用您喜欢的任何条件从四个阵列中的每一个中选择一个哈希。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM