我有对象数组"命令"。我想在我的数组中获得第一个最常见的值,他经常拿一本书:
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"
答案 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)