我想采用这样的两种形式的哈希:
hash_1 = {:a=>{:b=>3, :c=>{:stuff1=>[{:d=>1, :e=>2}, {:d=>4, :e=>2}], :stuff2=>[{:f=>33, :g=>44}, {:f=>55, :g=>66}], :h=>4}}}
hash_2 = {:a=>{:b=>3, :c=>{:stuff1=>[{:d=>8, :e=>5}, {:d=>7, :e=>5}], :stuff2=>[{:f=>45, :g=>89}, {:f=>78, :g=>67}], :h=>4}}}
然后取回(注意:stuff1
和:stuff2
加在一起):
result = {:a=>{:b=>3, :c=>{:stuff1=>[{:d=>1, :e=>2}, {:d=>4, :e=>2}, {:d=>8, :e=>5}, {:d=>7, :e=>5}], :stuff2=>[{:f=>33, :g=>44}, {:f=>55, :g=>66}, {:f=>45, :g=>89}, {:f=>78, :g=>67}], :h=>4}}}
我发现了这个post,但我的情况是嵌套哈希,所以任何一些好的红宝石手的帮助都会受到赞赏。
基本上,当与这些键对应的值为 arrays 时,我想“合并”相同命名键的数组值。当然,以下替换 hash_1
的{{1}}数组与:stuff1
的{{1}}数组(以及hash_2
类似) ,但我想要一个数组':stuff1
'类型的合并,而不是更新/替换,或合并! ...
:stuff2
我正在使用ruby 1.9.2,顺便说一句。我知道哈希最近有所更新,但我认为这不会影响答案。
谢谢!
答案 0 :(得分:1)
您可以为merge方法定义块,将为每个复制键调用此块。
hash_1.merge(hash_2) do |key, old_value, new_value|
old_value + new_value
end
答案 1 :(得分:1)
# adapted from http://snippets.dzone.com/posts/show/4706
class Hash
def deep_merge_with_array_values_concatenated(hash)
target = dup
hash.keys.each do |key|
if hash[key].is_a? Hash and self[key].is_a? Hash
target[key] = target[key].deep_merge_with_array_values_concatenated(hash[key])
next
end
if hash[key].is_a?(Array) && target[key].is_a?(Array)
target[key] = target[key] + hash[key]
else
target[key] = hash[key]
end
end
target
end
end
p hash_1.deep_merge_with_array_values_concatenated(hash_2)
答案 2 :(得分:0)
我认为规格并不完整。无论如何,一个函数递归方法(第二个哈希只用于连接数组值的值):
class Hash
def concat_on_common_array_values(hash)
Hash[map do |key, value|
if value.is_a?(Hash) && hash[key].is_a?(Hash)
[key, value.concat_on_common_array_values(hash[key])]
elsif value.is_a?(Array) && hash[key].is_a?(Array)
[key, value + hash[key]]
else
[key, value]
end
end]
end
end
p hash_1.concat_on_common_array_values(hash_2)
# {:a=>{:b=>3, :c=>{:stuff1=>[{:d=>1, :e=>2}, {:d=>4, :e=>2}, {:d=>8, :e=>5}, {:d=>7, :e=>5}], :stuff2=>[{:f=>33, :g=>44}, {:f=>55, :g=>66}, {:f=>45, :g=>89}, {:f=>78, :g=>67}], :h=>4}}}