Each key in a hash has a value that's also a hash.
{ 100 => { 1 => 'ruby', 2 => 'enumerables' }, 50 => { 3 => 'can', 4 => 'cause' }, 15 => { 5 => 'occassional', 6 => 'insanity' } }
For each hash object, I want to discard the top-level key, and replace it with the key and value of the nested hash objects.
{
1 => 'ruby',
2 => 'enumerables',
3 => 'can',
4 => 'cause',
5 => 'occasional',
6 => 'insanity'
}
I have it working, but my method uses a merge!
, and requires creating another hash to store the values. I'm curious to see if it can be done in one line. I tried to use reduce()
, but could not make it work.
While it isn't as brief as some of the other answers, I think
each_with_object
deserves a representation.This works:
Edit: Another option, using
reduce
(which is the same asinject
), and noting tokland's comment that to_proc is automatically called when you use a symbol:Then it becomes not only concise but very readable.
I like the answer by @MarkThomas best, but for speed and memory efficiency I suggest:
Benchmarking 200,000 iterations of the current answers shows this to be the fastest:
Since the comment by @tokland—
original.values.reduce(:update)
—modifies the original hash we cannot compare it directly to the other methods. However, if we modify all tests to put a duplicate of the first hash back into the original each iteration, @tokland's answer becomes the fastest, though still not quite as fast as mine:If you need absolute speed and it's OK to modify the original values, use @tokland's answer. If you do so and want to preserve the original unmerged hashes unscathed, then you can:
Note that your question title says traverse; if you don't really want to merge the values—if you might want to visit a duplicate key twice instead of last-in-wins—then simply do:
Just took a stab at it, first try was brute force and better methods (in both senses of the word...) are out there.
Since you don't value about the top level keys, use #values to get an array of the values (in this case, also hashes). Then you can use #inject to build up a new hash, merging them as you go.
There are probably other ways to do it.