How to find max value grouped by multiple keys in array of hashes?

霸气de小男生 提交于 2019-12-13 13:24:53

问题


Have data that has this kind of structure. Will be in ascending order by 'c'.

[ { 'a' => 1, 'b' => 1, 'c' =>  1, 'd' => '?' },
  { 'a' => 1, 'b' => 1, 'c' =>  2, 'd' => '?' },
  { 'a' => 1, 'b' => 1, 'c' =>  3, 'd' => '?' },
  { 'a' => 1, 'b' => 2, 'c' =>  4, 'd' => '?' },
  { 'a' => 1, 'b' => 2, 'c' =>  5, 'd' => '?' },
  { 'a' => 2, 'b' => 1, 'c' =>  6, 'd' => '?' },
  { 'a' => 2, 'b' => 1, 'c' =>  7, 'd' => '?' },
  { 'a' => 2, 'b' => 1, 'c' =>  8, 'd' => '?' },
  { 'a' => 2, 'b' => 2, 'c' =>  9, 'd' => '?' },
  { 'a' => 2, 'b' => 2, 'c' => 10, 'd' => '?' } ]

Want array of the max value of 'c' grouped by each unique combination of 'a' and 'b'.

[ { 'a' => 1, 'b' => 1, 'c' =>  3, 'd' => '?' },
  { 'a' => 1, 'b' => 2, 'c' =>  5, 'd' => '?' },
  { 'a' => 2, 'b' => 1, 'c' =>  8, 'd' => '?' },
  { 'a' => 2, 'b' => 2, 'c' => 10, 'd' => '?' } ]

The other keys need to be retained but are not otherwise related to the transformation. The best I could figure out so far is to reverse the array (thus descending ordered by 'c'), uniq by 'a' an 'b', and reverse array again. But I am depending on the implementation of uniq_by always returning the first unique item found. The specification doesn't say that, so I am worried about relying on that behavior since it could change in future versions. Also wondering if this may be a really inefficient method.

@data.reverse!.uniq!{|record| [record['a'],record['b']]}.reverse!

Is there a better and more efficient way to do this? If you do have a better way, can you also please explain it instead of just giving me a super nasty one-liner that I may not be able to decipher.


回答1:


That's actually fairly easy:

a.group_by { |h| h.values_at("a", "b") }.map { |_, v| v.max_by { |h| h["c"] } } 

Or with nicer formatting:

a.group_by do |h|
  h.values_at("a", "b") 
end.map do |_, v| 
  v.max_by { |h| h["c"] }
end

Explanation: first we use Enumerable#group_by to create a Hash with the combinations of "a" and "b" (extracted with Hash#values_at) as the keys and all hashes with that combination as the values. We then map over this hash, ignore the keys and select the element with the maximum value for "c" from the array with Enumerable#max_by.



来源:https://stackoverflow.com/questions/10621721/how-to-find-max-value-grouped-by-multiple-keys-in-array-of-hashes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!