[英]How to combine the value of multiple hashes within an array by the same key
I have an array of hashes like so: 我有一系列的哈希像这样:
[{"apple"=>5}, {"banana"=>4}, {"orange"=>6}, {"apple"=>4}, {"orange"=>2}]
How I do get to: 我怎么做到:
[{"apple"=>9}, {"banana"=>4}, {"orange"=>8}]
There's also: 还有:
cache = Hash.new { |h, k| h[k] = { k => 0 } }
aoh.flat_map(&:to_a)
.each_with_object(cache) { |(k,v),h| h[k][k] += v }
.values
Or in more pieces to be a little clearer: 或者更多的部分更清楚一点:
cache = Hash.new { |h, k| h[k] = { k => 0 } }
sum = -> ((k, v), h) { h[k][k] += v }
summary = aoh.flat_map(&:to_a)
.each_with_object(cache, &sum)
.values
The somewhat odd looking cache
Hash does two things at once: 看起来有点奇怪的
cache
Hash同时做两件事:
There are many ways, as you will soon see. 你会很快看到很多方法。 Here's one:
这是一个:
arr = [{"apple"=>5}, {"banana"=>4}, {"orange"=>6}, {"apple"=>4}, {"orange"=>2}]
arr.flat_map(&:to_a)
.group_by(&:first)
.map { |k,a| { k=>(a.reduce(0) { |tot,(_,v)| tot+v }) } }
#=> [{"apple"=>9}, {"banana"=>4}, {"orange"=>8}]
The steps: 步骤:
a = arr.flat_map(&:to_a)
#=> [["apple",5], ["banana",4], ["orange",6], ["apple",4], ["orange",2]]
b = a.group_by(&:first)
#=> {"apple"=>[["apple", 5], ["apple", 4]],
# "banana"=>[["banana", 4]],
# "orange"=>[["orange", 6], ["orange", 2]]}
b.map { |k,a| { k=>(a.reduce(0) { |tot,(_,v)| tot+v }) } }
#=> [{"apple"=>9}, {"banana"=>4}, {"orange"=>8}]
Let's take a closer look at b.map
: 让我们仔细看看
b.map
:
enum = b.map
#=> #<Enumerator: {
# "apple"=>[["apple", 5], ["apple", 4]],
# "banana"=>[["banana", 4]],
# "orange"=>[["orange", 6], ["orange", 2]]
# }:map>
The first element of enum
is passed (by Enumerator#each , which in turn calls Array#each ) to the block and assigned to the block variables. enum
的第一个元素(通过Enumerator#each ,它又调用Array#each )传递给块并分配给块变量。 We can simulate that using Enumerator#next : 我们可以使用Enumerator#next来模拟它:
k,a = enum.next
#=> ["apple", [["apple", 5], ["apple", 4]]]
k #=> "apple"
a #=> [["apple", 5], ["apple", 4]]
To calculate: 计算:
c = a.reduce(0) { |tot,(_,v)| tot+v }
#=> 9
the first element of a
is passed to the block and the block variables are assigned: 的第一个元素
a
被传递到块和块变量被分配:
tot, (_,v) = 0, ["apple", 5]
#=> [0, ["apple", 5]]
tot #=> 0
v #=> 5
We then compute: 然后我们计算:
tot + 5
#=> 0+5 => 5
which is returned to reduce
to become the updated value of tot
. 返回以
reduce
以成为tot
的更新值。 The second value of a
is passed in: 的第二值
a
传入:
tot, (_,v) = 5, ["apple", 4]
tot #=> 5
v #=> 4
and we calculate and return: 我们计算并返回:
tot+4
# 5+4 => 9
so: 所以:
{ k=>tot }
#=> { "apple"=>9 }
is the mapped value of the first element of a
. 是
a
的第一个元素的映射值。 The remaining mapped values are computed similarly. 其余映射值的计算方法类似。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.