I would like to merge a nested hash.
a = {:book=>
[{:title=>"Hamlet",
:author=>"William Shakespeare"
}]}
b = {:book=>
[{:title=>"Pride and Prejudice",
:author=>"Jane Austen"
}]}
I would like the merge to be:
{:book=>
[{:title=>"Hamlet",
:author=>"William Shakespeare"},
{:title=>"Pride and Prejudice",
:author=>"Jane Austen"}]}
What is the nest way to accomplish this?
For rails 3.0.0+ or higher version there is the deep_merge function for ActiveSupport that does exactly what you ask for.
To add on to Jon M and koendc's answers, the below code will handle merges of hashes, and :nil as above, but it will also union any arrays that are present in both hashes (with the same key):
For variety's sake - and this will only work if you want to merge all the keys in your hash in the same way - you could do this:
When you pass a block to
Hash#merge
,k
is the key being merged, where the key exists in botha
andb
,x
is the value ofa[k]
andy
is the value ofb[k]
. The result of the block becomes the value in the merged hash for keyk
.I think in your specific case though, nkm's answer is better.
A little late to answer your question, but I wrote a fairly rich deep merge utility awhile back that is now maintained by Daniel Deleo on Github: https://github.com/danielsdeleo/deep_merge
It will merge your arrays exactly as you want. From the first example in the docs:
So if you have two hashes like this:
It won't merge :y (because int and array aren't considered mergeable) - using the bang (!) syntax causes the source to overwrite.. Using the non-bang method will leave dest's internal values alone when an unmergeable entity is found. It will add the arrays contained in :x together because it knows how to merge arrays. It handles arbitrarily deep merging of hashes containing whatever data structures.
Lots more docs on Daniel's github repo now..
Or
All answers look to me overcomplicated. Here's what I came up with eventually:
P.S. use as public, WTFPL or whatever license