Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

Combining / Merging two Ho(H|A)s

by jkva (Chaplain)
on Feb 21, 2006 at 20:57 UTC ( #531794=perlquestion: print w/ replies, xml ) Need Help??
jkva has asked for the wisdom of the Perl Monks concerning the following question:

Esteemed Monks.

Let's say I have two hashes :
%hash1 = ( foo => 'bar', baz => { quux => 'qwe', rty => 'uiop', }, perl => ['monks', 'monastery', 'robes'], ) %hash2 = ( wizardry => 'hocus-pocus', foo => 'f00', baz => { grail => 'arthur', }, perl => ['yayy', 'yippee'], hash3 => {key1 => 'value1', key2 => 'value2', }, );

I'd like to "add" %hash2 to %hash1, and existing data should be overwritten while nonexistent data should be added. What would be the best approach to this?

-- jkva

Comment on Combining / Merging two Ho(H|A)s
Download Code
Re: Combining / Merging two Ho(H|A)s
by xorl (Deacon) on Feb 21, 2006 at 20:59 UTC
    There's nothing like the brute force method
    foreach my $key2 (keys %hash2) { $hash1{$key2} = $hash2{$key2}; }
    Code untested and probably not has elegant as it could be.
      Brute it is. Perhaps I didn't specify that well enough - in this case the nested hashes overwrite eachother instead of merging. This is not what I intend.
      Thanks for your reply, though.
Re: Combining / Merging two Ho(H|A)s
by GrandFather (Cardinal) on Feb 21, 2006 at 21:02 UTC

    You could try something recursive like this:

    use warnings; use strict; use Data::Dump::Streamer; my %hash1 = ( foo => 'bar', baz => { quux => 'qwe', rty => 'uiop', }, perl => ['monks', 'monastery', 'robes'], ); my %hash2 = ( wizardry => 'hocus-pocus', foo => 'f00', baz => { grail => 'arthur', }, perl => ['yayy', 'yippee'], hash3 => {key1 => 'value1', key2 => 'value2', }, ); merge (\%hash2, \%hash1); Dump (\%hash1); sub merge { my ($source, $target) = @_; for (keys %$source) { if ('ARRAY' eq ref $target->{$_}) { push @{$target->{$_}}, @{$source->{$_}}; } elsif ('HASH' eq ref $target->{$_}) { merge ($source->{$_}, $target->{$_}); } else { $target->{$_} = $source->{$_}; } } }

    DWIM is Perl's answer to Gödel
Re: Combining / Merging two Ho(H|A)s
by Corion (Pope) on Feb 21, 2006 at 21:02 UTC

    If you just want the data to be overwritten, it's easy and no loop is needed when you use a hash slice:

    @hash1{ keys %hash2 } = values %hash2;

    Oh - now I see that you wanted this done recursively. Then you'll need something like GrandFather wrote

Re: Combining / Merging two Ho(H|A)s
by ikegami (Pope) on Feb 21, 2006 at 21:14 UTC
    When dealing with data structures and you want something to occur at all levels, it is said to occur "in depth" or "deeply", or is said to be "deep". GrandFather's solution merges deeply, while xorl and Corion's solution merge shallowly.
Re: Combining / Merging two Ho(H|A)s
by Roy Johnson (Monsignor) on Feb 21, 2006 at 21:35 UTC
    Have a look at Hash::Merge.

    Caution: Contents may have been coded under pressure.
Re: Combining / Merging two Ho(H|A)s
by jdporter (Canon) on Feb 21, 2006 at 23:22 UTC

    You didn't say what should happen when there are existing values in the two hashes, but their types are different. For example,

    %h1 = ( foo => 1, ); %h2 = ( foo => { bar => 2, }, );
    Do you have reason to believe this won't happen?

    We're building the house of the future together.
      Very very good point. It is possible. I'd say the first hash's value should be overwritten by the second one.
      GrandFather's code can be easily changed to check for REF differences and act accordingly.

        Right; but I would definitely look into Hash::Merge (Roy_Johnson's suggestion).

        We're building the house of the future together.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://531794]
Approved by GrandFather
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others perusing the Monastery: (11)
As of 2014-10-21 07:44 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    For retirement, I am banking on:










    Results (98 votes), past polls