Ruby 如何使用不同的哈希值对数组中的值求和
我想对数组中相同项的总值求和 我有一个数组Ruby 如何使用不同的哈希值对数组中的值求和,ruby,arrays,hash,Ruby,Arrays,Hash,我想对数组中相同项的总值求和 我有一个数组 [{"a"=>1},{"b"=>2},{"c"=>3},{"a"=>2},{"b"=>4}] 我想得到结果 [{"a"=>3},{"b"=>6},{"c"=>3}] 哪种方法可以做到这一点?有很多方法可以做到这一点。看到一些,甚至一些可能是不寻常的和/或不是特别有效的是很有启发性的 还有一种方法: arr = [{"a"=>1},{"b"=>2},{"c"=>3},{"a"=>
[{"a"=>1},{"b"=>2},{"c"=>3},{"a"=>2},{"b"=>4}]
我想得到结果
[{"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
,我们可以将的块缩减为:
{ |t,g| t+g[k].to_i }
有很多方法可以做到这一点。看到一些,甚至一些可能是不寻常的和/或不是特别有效的是很有启发性的
还有一种方法:
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
,我们可以将的块缩减为:
{ |t,g| t+g[k].to_i }
如果:
然后你可以做:
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.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}]
或:
每当您不想以一对一的方式转换集合时,它就是#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
中时,才会调用该块。然后,我们将散列分解为一个散列数组。每当您希望以非一对一的方式转换集合时,它就是#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
中时,才会调用该块。然后,我们将散列分解为一个散列数组。可以按如下方式完成
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}]
可以按如下方式进行
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}]
您需要添加.map{k,v{k=>v}}
或类似于结尾的内容,以将结果转换为指定的形式(哈希数组)。它应该生成:[{“a”=>3},{“b”=>6},{“c”=>3}
而不是{“b”=>6,“a”=>3,“c”=>3}
。我认为你需要像上面提到的@CarySwoveland那样做。你需要添加.map{k,v{k=>v}}
或类似的东西来将结果转换成指定的形式(哈希数组)。它应该产生:[{“a”=>3},{“b”=>6},{“c”=>3}
而不是{b”=>6,“a”=>3,“c”=>3}
。我想你需要做一些像上面提到的@CarySwoveland那样的事情。#每个带有_object的
都是我要找的,无论是否有人使用过。:-)但是你做到了,所以你节省了我的时间。您不需要来创建一个。(为什么?)。2.你不需要;h
带有每个带有对象的对象(这就是@Arup建议后者的原因)。3.“arr”
是合适的名称吗?格式有了很大的改进。@CarySwoveland是的,没错。。这就是为什么如果我不是被迫的话,我不会经常使用#inject
:P#每个带有_对象的_
都是我要寻找的,无论是否有人使用过。:-)但是你做到了,所以你节省了我的时间。您不需要来创建一个。(为什么?)。2.你不需要;h
带有每个带有对象的对象(这就是@Arup建议后者的原因)。3.“arr”
是合适的名称吗?格式有了很大的改进。@CarySwoveland是的,没错。。这就是为什么如果我不是被迫的话,我不会经常使用#inject
:P