1

我有一组类别及其值存储为哈希列表:

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}s 的所有实例的计数,然后创建哈希?我应该给出不同的基本情况来减少和更改正文以检查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
4

3 回答 3

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

但老实说,最好去创建这个数组的任何地方,并将其更改为像这样的聚合值。

于 2012-05-18T07:22:45.080 回答
0

使用一些方便的抽象的功能方法 - 无需重新发明轮子 - 从方面

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}}
于 2012-05-18T07:25:59.407 回答
0

您的代码的问题是:memo没有保存该值。使用循环外的变量来保存值就可以了:

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 -哈希是错误的

于 2012-05-18T08:44:10.127 回答