[英]How to sum values in an array with different hash
我想对数组中相同项目的总值求和。
我有一个数组
[{"a"=>1},{"b"=>2},{"c"=>3},{"a"=>2},{"b"=>4}]
我想得到的结果
[{"a"=>3},{"b"=>6},{"c"=>3}]
哪种方法可以做到?
如果:
array = [{"a"=>1},{"b"=>2},{"c"=>3},{"a"=>2},{"b"=>4}]
那么您可以执行以下操作:
array.inject(Hash.new{|h,k| h[k] = 0})
{ |h, a| k, v = a.flatten; h[k] += v; h }.
map{|arr| Hash[*arr] }
#=> [{"a"=>3}, {"b"=>6}, {"c"=>3}]
要么:
array.each_with_object(Hash.new{|h,k| h[k] = 0})
{ |a, h| k, v = a.flatten; h[k] += v }.
map{|arr| Hash[*arr] }
#=> [{"a"=>3}, {"b"=>6}, {"c"=>3}]
可以如下进行
array.group_by { |h| h.keys.first }.
values.
map {|x| x.reduce({}) { |h1, h2| h1.merge(h2) { |_, o, n| o + n } }
#=> [{"a"=>3}, {"b"=>6}, {"c"=>3}]
有很多方法可以做到这一点。 看到一些,甚至是一些可能不正常和/或效率不高的指令是很有启发性的。
这是另一种方式:
arr = [{"a"=>1},{"b"=>2},{"c"=>3},{"a"=>2},{"b"=>4}]
arr.flat_map(&:keys)
.uniq
.map { |k| { k=>arr.reduce(0) { |t,g| t + (g.key?(k) ? g[k] : 0) } } }
#=> [{"a"=>3}, {"b"=>6}, {"c"=>3}]
由于nil.to_i => 0
,我们可以改为将reduce
的块编写为:
{ |t,g| t+g[k].to_i }
每次您要以非一对一的方式转换集合时, #reduce
工作。 对于一对一转换,我们使用#map
。
array.reduce({}) { |h, acc| acc.merge(h) {|_k, o, n| o+n } }.zip.map(&:to_h)
# => [{"b"=>6}, {"a"=>3}, {"c"=>3}]
在这里,我们将reduce用作初始值{}
,并将其作为acc
参数传递给块,然后使用带有手动“冲突解决”功能的#merge
。 这意味着仅当我们尝试合并的键已在方法接收器acc
已经存在时才调用该块。 之后,我们将散列分解为散列数组。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.