我有一组类别及其值存储为哈希列表:
r = [{:A => :X}, {:A => :Y}, {:B => :X}, {:A => :X}, {:A => :Z}, {:A => :X},
{:A => :X}, {:B => :Z}, {:C => :X}, {:C => :Y}, {:B => :X}, {:C => :Y},
{:C => :Y}]
我希望得到每个值的计数以及它的类别,如下所示:
{:A => {:X => 4, :Y => 1, :Z => 1},
:B => {:X => 2, :Z => 1},
:C => {:X => 1, :Y => 3}}
我怎样才能有效地做到这一点?
这是我到目前为止所得到的(它返回不一致的值):
r.reduce(Hash.new(Hash.new(0))) do |memo, x|
memo[x.keys.first][x.values.first] += 1
memo
end
我应该首先计算特定{:cat => :val}
的所有实例的计数,然后创建哈希吗?我是否应该提供不同的基础案例来减少和更改正文以检查nil
个案例(并在nil
时分配为零)而不是总是添加1?
编辑:
我最终更改了我的代码并使用以下方法来更简洁地实现嵌套哈希:
r.map do |x|
[x.keys.first, x.values.last]
end.reduce({}) do |memo, x|
memo[x.first] = Hash.new(0) if memo[x.first].nil?
memo[x.first][x.last] += 1
memo
end
答案 0 :(得分:0)
不确定“不一致的值”是什么意思,但你的问题是你注入的哈希是不记得它的结果
r.each_with_object(Hash.new { |h, k| h[k] = Hash.new 0 }) do |individual, consolidated|
individual.each do |key, value|
consolidated[key][value] += 1
end
end
但老实说,最好只去你制作这个数组的地方并将其改为聚合这样的值。
答案 1 :(得分:0)
使用一些方便的抽象的功能方法 - 无需重新发明轮子 - 来自facets:
require 'facets'
r.map_by { |h| h.to_a }.mash { |k, vs| [k, vs.frequency] }
#=> {:A=>{:X=>4, :Y=>1, :Z=>1}, :B=>{:X=>2, :Z=>1}, :C=>{:X=>1, :Y=>3}}
答案 2 :(得分:0)
您的代码问题是:备忘录没有保留该值。 在循环外部使用一个变量来保持该值是正常的:
memo = Hash.new {|h,k| h[k] = Hash.new {|hh, kk| hh[kk] = 0 } }
r.each do |x|
memo[x.keys.first][x.values.first] += 1
end
p memo
而且,如下所示,直接在哈希中嵌套哈希是不行的:
# NOT RIGHT
memo = Hash.new(Hash.new(0))
memo = Hash.new({})
以下是有关设置默认值问题的详情的链接: http://www.themomorohoax.com/2008/12/31/why-setting-the-default-value-of-a-hash-to-be-a-hash-is-wrong