问题
I have a nested hash:
{
["X", 1, 2, 3]=> {
["X", "O", 2, 3]=> {
["X", "O", "X", 3]=>["X", "O", "X", "O"]
}
}
}
I want to merge a given nested hash:
{
["X", 1, 2, 3]=> {
["X", "O", 2, 3]=> {
["X", "O", 2, "X"] => ["X", "O", "O", "X"]
}
}
}
such that:
{
["X", 1, 2, 3]=> {
["X", "O", 2, 3]=> {
["X", "O", "X", 3]=>["X", "O", "X", "O"],
["X", "O", 2, "X"] => ["X", "O", "O", "X"]
}
}
}
What's the best way?
The hashes I'll be merging will have an equivalent key at an arbitrary depth of nested-ness. The value of the last nested hash will always be different from all the other hashes.
回答1:
If you're sure that all the duplicate keys have values that are Hashes, you can use a recursive Hash#merge with block :
def deep_merge(h1,h2)
h1.merge(h2){|k,v1,v2| deep_merge(v1,v2) }
end
With your example :
{["X", 1, 2, 3]=>
{["X", "O", 2, 3]=>
{["X", "O", "X", 3]=>["X", "O", "X", "O"],
["X", "O", 2, "X"]=>["X", "O", "O", "X"]}}}
NOTE: This method doesn't work in the general case, and shouldn't be used for anything else than the structure defined in the question. It will fail for deep_merge({a:1},{a:2})
.
If you don't have information about the nested keys and values :
def deep_merge(h1,h2)
h1.merge(h2){|k,v1,v2| v1.is_a?(Hash) && v2.is_a?(Hash) ? deep_merge(v1,v2) : v2}
end
In case of a conflict with values that aren't both Hashes, the second value will overwrite the first one.
Both methods return a new hash, and do not modify either h1 or h2.
NOTE: This method is available in Rails.
来源:https://stackoverflow.com/questions/41109599/ruby-merging-a-nested-hash-without-overwriting