是否有一种更智能的方法可以将所有键值相加:
hash_1 = {
41 => {"a" => {:a => 4, :b => 8, :c => 3}},
56 => {"b" => {:a => 5, :b => 4, :c => 8}},
57 => {"c" => {:a => 8, :b => 9, :c => 3}},
}
得到结果:
result_hash = {a: 17, b: 21, c: 14}
我可以通过迭代每个哈希获得上面的结果,但我正在寻找另一种方法来实现它。
答案 0 :(得分:3)
a.
values.
flat_map(&:values).
flat_map(&:to_a).
each_with_object({}) { |(key, value), b| b[key] = b[key].to_i + value }
答案 1 :(得分:3)
hash_1.map { |_, v| v.to_a.last.last }.
reduce { |e, acc| acc.merge(e) { |_, v1, v2| v1 + v2 } }
#⇒ {:a=>17, :b=>21, :c=>14}
答案 2 :(得分:1)
您可以改进Hash::each
,以便您轻松执行任务:
module HashRecursive
refine Hash do
def each(recursive=false, &block)
if recursive
Enumerator.new do |yielder|
self.map do |key, value|
value.each(recursive=true).map{ |key_next, value_next|
yielder << [[key, key_next].flatten, value_next]
} if value.is_a?(Hash)
yielder << [[key], value]
end
end.entries.each(&block)
else
super(&block)
end
end
alias_method(:each_pair, :each)
end
end
using HashRecursive
以下是您的任务的解决方案:
def sum_hashes(hash) # This method will do the job
result_hash = {}
hash.each(recursive=true) do |keys, value|
if keys.size == 2
result_hash.merge!(value) do |key, value1, value2|
[value1, value2].all? {|v| v.is_a?(Integer)} ? value1+value2 : value2
end
end
end
result_hash
end
# Here is your question's example
hash_1 = {
41 => {"a" => {:a => 4, :b => 8, :c => 3}},
56 => {"b" => {:a => 5, :b => 4, :c => 8}},
57 => {"c" => {:a => 8, :b => 9, :c => 3}}
}
puts sum_hashes(hash_1) # {:a=>17, :b=>21, :c=>14}
# This will work for anything that has similar pattern
hash_2 = {
:a => { "p" => {:a => 1, :b => 2, :c => 0, :d => 5 }},
3 => { "b" => {:a => 2, :b => 2, :c => 100, :d => 0 }},
404 => { "c" => {:a => 3, :b => 2, :c => -100, :d => 15 }},
'24' => { "2" => {:a => 4, :b => 2, :c => 300, :d => 25 }},
11 => { :h => {:a => 5, :b => 2, :c => -350, :d => 40 }},
:x => { "c" => {:a => 6, :b => 2, :c => 50, :d => 5 }}
}
puts sum_hashes(hash_2) # {:a=>21, :b=>12, :c=>0, :d=>90}
请查看this answer了解详情。