我试图获得一个新的数组散列,它将列出仅提供一次的 array(e) 散列中的每个 :name,并且该值应该是总分,它应该是相同 :name 下的分数总和数组(e)。
e = [
{:name => "Oyster", :score => 1000},
{:name => "Tiger", :score => 2000},
{:name => "Frog", :score => 2300},
{:name => "Frog", :score => 1220},
{:name => "Tiger", :score => 200},
{:name => "Frog", :score => 1000},
{:name => "Oyster", :score => 2000},
{:name => "Frog", :score => 300},
{:name => "Monkey", :score => 500},
{:name => "Oyster", :score => 3300}
]
我在谷歌上搜索了「hash array ruby」和 ruby 的文档,但还没有得到任何非常有用的信息。
我试图通过执行以下操作来解决这个问题:
f = e.map{|t|t[:name]}.uniq
n = Hash[f.map{|v|[v,0]}]
result = n.map{|key, value|e.map{|t| if key == t[:name]; n[key] += t[:score].to_i end}}
但结果是
[[1000, nil, nil, nil, nil, nil, 3000, nil, nil, 6300], [nil, 2000, nil, nil, 2200, nil, nil, nil, nil, nil], [nil, nil, 2300, 3520, nil, 4520, nil, 4820, nil, nil], [nil, nil, nil, nil, nil, nil, nil, nil, 500, nil]]
这与我的预期完全不同。如果我们想达到非常简洁的结果,我们应该怎么做。
您可以使用group_by
by 对散列进行分组:name
,然后:score:
使用reduce
with对值求和merge
,如下所示:
e.group_by { |h| h[:name] }.map do |_, v|
v.reduce do |acc, h|
acc.merge(h) { |k, ov, nv| k == :name ? ov : ov + nv }
end
end
#=> [{:name=>"Oyster", :score=>6300}, {:name=>"Tiger", :score=>2200}, {:name=>"Frog", :score=>4820}, {:name=>"Monkey", :score=>500}]
解释:
group_by { |h| h[:name] }
按名称对所有散列进行分组,结果如下:
{
"Oyster"=>[
{:name=>"Oyster", :score=>1000},
{:name=>"Oyster", :score=>2000},
{:name=>"Oyster", :score=>3300}
],
"Tiger"=>[...]
}
.map
迭代生成的散列,忽略分组键(_
变量)并仅使用值(v
变量,包含分组散列的数组)来求和每个散列的分数(参见下一步)。
reduce
score
通过将数组中的所有散列合并在一起来对的值求和(acc
是累积值/散列,h
是迭代的当前值/散列)。请注意,merge
它与块一起使用,而不是替换重复键的值(如merge
没有块的),它将使用块中的代码替换其值,其中:
k
是正在合并的散列的当前键。ov
是acc
给定键的旧值(即哈希值)。nv
是h
给定键的新值(即哈希值)。因此,在按 对散列进行分组后name
,它迭代每组散列并将它们合并为一个,首先评估当前键是否是:name
,如果是,则保留旧值(例如"Oyster"
),否则(例如:score
)它将求和用新值替换旧值,并score
用该结果替换 的值,在每次迭代中累加该值。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句