如何在散列数组中找到由多个键分组的最大值?

Dou*_*uch 4 ruby arrays hash max uniq

有这种结构的数据.将按'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' => '?' } ]
Run Code Online (Sandbox Code Playgroud)

想要通过'a'和'b'的每个唯一组合分组的'c'的最大值的数组.

[ { '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' => '?' } ]
Run Code Online (Sandbox Code Playgroud)

其他键需要保留,但与转换无关.到目前为止,我能想到的最好的方法是反转数组(因此按'c'降序排序),uniq'a'和'b',以及反向数组.但我依赖于uniq_by的实现总是返回找到的第一个唯一项目.规范没有说明,所以我担心依赖于这种行为,因为它可能在未来的版本中发生变化.还想知道这可能是一个非常低效的方法.

@data.reverse!.uniq!{|record| [record['a'],record['b']]}.reverse!
Run Code Online (Sandbox Code Playgroud)

有没有更好,更有效的方法来做到这一点?如果你有一个更好的方法,你也可以解释它,而不是只给我一个超级讨厌的单行,我可能无法破译.

Mic*_*ohl 11

这实际上相当容易:

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

或者使用更好的格式:

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

说明:第一,我们使用可枚举#GROUP_BY创建Hash与的组合 "a""b"(与提取的哈希#values_at作为密钥和与该组合作为值的所有散列).然后,我们映射此哈希,忽略键并"c"从具有Enumerable#max_by的数组中选择具有最大值的元素.

  • @Flexoid:没有特殊意义,它是我不关心的参数,在许多语言中,习惯上使用下划线表示名称. (3认同)
  • `_`确实有特殊意义或至少[得到特殊处理](http://stackoverflow.com/a/9560198/479863)在某些情况下,使用`_`作为*我不在乎的惯例*参数在解释器中具有硬连线支持.这只是一个评论虽然:) (3认同)