我有一系列哈希:
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
你可以一起merge
哈希值,添加两个哈希值中的值:
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}
如果您的真实散列具有对+
不能很好响应的键,则可以访问key
,您可以设置case语句,以便在需要时以不同方式处理键。
您可以创建如下方法来获得结果
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}
您还可以使用枚举器each_with_object,使用哈希作为对象。
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)
对于任何键都意味着initialise the hash to default value 0
,例如:
h = Hash.new(0)
h[:whathever_key] # => 0
我感兴趣的是“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倍。
这是基准代码https://gist.github.com/landovsky/6a1b29cbf13d0cf81bad12b6ba472416