Ruby 在具有相同密钥的数组中合并/添加哈希

Ruby 在具有相同密钥的数组中合并/添加哈希,ruby,hash,Ruby,Hash,我有一个哈希数组: array = [ {"points": 0, "block": 3}, {"points": 25, "block": 8}, {"points": 65, "block": 4} ] 我需要合并散列。我需要输出为: {"points": 90, "block": 15} 如果您拥有此结构中提到的阵列: array = [ {"points": 0, "block": 3}, {"points": 25, "block": 8}, {"point

我有一个哈希数组:

array = [
  {"points": 0, "block": 3},
  {"points": 25, "block": 8},
  {"points": 65, "block": 4}
]
我需要合并散列。我需要输出为:

{"points": 90, "block": 15}

如果您拥有此结构中提到的阵列:

array = [
  {"points": 0, "block": 3},
  {"points": 25, "block": 8},
  {"points": 65, "block": 4}
]
您可以使用以下代码来实现您的目标:

result = {
  points: array.map{ |item| item[:points] }.inject(:+),
  block: array.map{ |item| item[:block] }.inject(:+)
}
您将得到以下结果:

{:points=>90, :block=>15}
注意:这将在数组上迭代两次。我正试图找到一种更好的方法来迭代一次,并且仍然拥有同样优雅/易于准备的代码

如果要更一般地执行此操作(比
:points
:block
更多的键),则可以使用以下代码:

array = [
  {"points": 0, "block": 3},
  {"points": 25, "block": 8},
  {"points": 65, "block": 4}
]

keys = [:points, :block] # or you can make it generic with array.first.keys

result = keys.map do |key|
  [key, array.map{ |item| item.fetch(key, 0) }.inject(:+)]
end.to_h

您可以创建如下方法来获得结果

def process_array(array)
   points = array.map{|h| h[:points]}
   block = array.map{|h| h[:block]}
   result = {}
   result['points'] = points.inject{ |sum, x| sum + x }
   result['block'] = block.inject{ |sum, x| sum + x }
  result
end
使用数组输入调用该方法将得到预期的结果

[54] pry(main)> process_array(array)
=> {"points"=>90, "block"=>15}

您还可以使用枚举器,使用哈希作为对象

result = array.each_with_object(Hash.new(0)) {|e, h| h[:points] += e[:points]; h[:block] += e[:block] }
# => {:points=>90, :block=>15}
Hash.new(0)
表示任何键的
0
,例如:

h = Hash.new(0)
h[:whathever_key] # => 0
您可以将两个散列组合在一起,添加两个散列中的值:

result = array.reduce do |memo, next_hash|
  memo.merge(next_hash) do |key, memo_value, next_hash_value|
    memo_value + next_hash_value
  end
end
result # => {:points=>90, :block=>15}

如果你的真正散列中的键对
+
的响应不好,你可以访问
键,你可以设置一个case语句,根据需要以不同的方式处理键。

我对“Simple Lime”引入的
reduce
方法很感兴趣以及它如何在数组和每个散列的键上对简单迭代进行基准测试

以下是“迭代”方法的代码:

Hash.new(0).tap do |result|
  array.each do |hash|
    hash.each do |key, val|
      result[key] = result[key] + val
    end
  end
end
我很惊讶,“迭代”代码的性能是
reduce
方法的3倍


这是基准代码

嗯,我尝试了你给出的代码,它给出了我想要的。非常感谢。但我实际上有24个键,所以我必须映射每个键,我希望你能帮助我删除代码,我将非常感激。我的数组可能包含10+个哈希值,这有关系吗?我已经更新了我的代码,使其更加通用,您可以定义一组要求和的键。如果您谈论的是10+哈希和24个键,那么我不会关心性能。我认为这是一个过早的优化规模。