如何在哈希数组中找到最常见的值

时间:2017-04-17 14:18:23

标签: ruby

我有对象数组"命令"。我想在我的数组中获得第一个最常见的值,他经常拿一本书:

orders = [
        {'book' => '1', 'reader' => 'Denis' },
        {'book' => '2', 'reader' => 'Mike' },
        {'book' => '3', 'reader' => 'Denis' },
        {'book' => '3', 'reader' => 'Mike' },
        {'book' => '5', 'reader' => '2' }
        ]

我尝试过这种方法,但它只适用于字符串数组:['string', 'string'...]

def most_common_value(a)
  a.group_by(&:itself).values.max_by(&:size).first
end

预期结果:

=> "Denis"

4 个答案:

答案 0 :(得分:2)

key = 'reader'
x = orders.inject({}) do |a,i| 
 a[i[key]] = 0 unless a.has_key? i[key]
 a[i[key]] +=1
 a
end.max_by{|k,v| v}

返回:

=> ["Denis", 2] 

答案 1 :(得分:2)

我这样做:

orders = [
  {'book' => '1', 'reader' => 'Denis' },
  {'book' => '2', 'reader' => 'Mike' },
  {'book' => '3', 'reader' => 'Denis' },
  {'book' => '3', 'reader' => 'Mike' },
  {'book' => '5', 'reader' => '2' }
]

orders.each_with_object(Hash.new(0)) { |order, hash| hash[order['reader']] += 1 }.max_by { |k, v| v } 
# => ["Denis", 2]

问题是,如果有多个" max"然后将根据找到数据的顺序返回结果。例如,如果订单不同:

orders.push(orders.shift)
# => [{"book"=>"2", "reader"=>"Mike"},
#     {"book"=>"3", "reader"=>"Denis"},
#     {"book"=>"3", "reader"=>"Mike"},
#     {"book"=>"5", "reader"=>"2"},
#     {"book"=>"1", "reader"=>"Denis"}]

结果发生了变化:

orders.each_with_object(Hash.new(0)) { |order, hash| hash[order['reader']] += 1 }.max_by { |k, v| v } 
# => ["Mike", 2]

答案 2 :(得分:2)

我几天前看到这个,如果Array或Enumerable有一个mode_by,我觉得这很容易!好吧,我终于开始鞭打了一个。

实施mode_by

mode_by可能会返回与块匹配的项的子数组:

orders.mode_by{|order| order['reader']}
#=> [{'book'=>'1', 'reader'=>'Denis'}, {'book'=>'3', 'reader'=>'Denis'}]

并获得您想要的结果:

orders.mode_by{|order| order['reader']}.first['reader']
#=> "Denis"

因此,让我们实现mode_by

class Array
  def mode_by(&block)
    self.group_by(&block).values.max_by(&:size)
  end
end

et voila!

自定义替代

在您的情况下,您不需要返回数组元素。让我们通过实现一些能够准确返回所需内容的东西来进一步简化,这是块出现最多的第一个结果。我们称之为mode_of

class Array
  def mode_of(&block)
    self.group_by(&block).max_by{|k,v| v.size}.first
  end
end

现在你可以这样做:

orders.mode_of{|order| order['reader']}
#=> "Denis"

答案 3 :(得分:1)

使用group_bymax_by

orders.group_by { |h| h['reader']}.to_a.max_by {|x| x[1].length}.first

输出:

 => "Denis"