Beefy Boxes and Bandwidth Generously Provided by pair Networks
XP is just a number
 
PerlMonks  

Merge hash into another hash

by GrandFather (Cardinal)
on Apr 29, 2007 at 06:11 UTC ( #612615=snippet: print w/ replies, xml ) Need Help??

Description: merge one hash into another using a hash slice. Note that the new values replace any previous values with the same key.
@target{keys %source} = values %source;
Comment on Merge hash into another hash
Download Code
Re: Merge hash into another hash
by ides (Deacon) on Apr 29, 2007 at 15:19 UTC

    That works great for simple hashes, but if you have a complex data structure you'll definitely want to check out Hash::Merge

    Frank Wiles <frank@revsys.com>
    www.revsys.com

      This is what I would definitely use for complex structure, as I would have different rules for certain keys at different depth levels.

      As for simple merge, I tend to use the opposite of what GrandFather uses. My target hashes are mostly new initialized ones, and the the source is taken as custom values that override the default. So I just stuff source into target. Because the source hash is actually a reference, it will be dereferenced.

      sub some_meth { my($self, $source) = @_; my %target = ( key1 => 'default_1', key2 => 'default_2', keyN => 'default_N', %$source, ); # do somethings with %target }
      Of course, GrandFather's technique can be applied as well. And I can see an advantage to have a chance to check the source prior to merging.
      my %target = ( # initialization ); %target{keys %$source} = values %$source if defined $source && ref $source eq 'HASH';

      Open source softwares? Share and enjoy. Make profit from them if you can. Yet, share and enjoy!

        For simple hashes, what's wrong with just:

        my %target = ( #initialize ); %target = (%target, %source)
        ? (with the issues of complex cases, source checking, and dereferencing aside (but perhaps fixable))

        jason.

Re: Merge hash into another hash
by eamallove (Initiate) on Nov 18, 2009 at 19:54 UTC
    To preserve the key->{value} structure of the hash, I had to create a recursive function. This works for me:
    sub merge_hashes { my ($x, $y) = @_; foreach my $k (keys %$y) { if (!defined($x->{$k})) { $x->{$k} = $y->{$k}; } else { $x->{$k} = merge_hashes($x->{$k}, $y->{$k}); } } return $x; }
Re: Merge hash into another hash
by ruzam (Curate) on Nov 18, 2009 at 23:54 UTC

    Unless I'm mistaken, both 'keys' and 'values' will make Perl gather up all the elements of each into temporary lists before even attempting to assign them. If %source is really huge, then that could be a problem?

    If I thought memory use was a concern I'd walk the key values instead.

    while (my($key, $value) = each %source) { $target{$key} = $value }

    But I imagine Perl is pretty good at handling temporary lists, so I doubt looping through the keys would be as fast.

    Update

    ... and just for fun

    Update Again (used the wrong target in the benchmark)

    cmpthese( -1, { grandfather => sub { my %t = %target; @t{keys %source} = values %source; }, sleepyjay => sub { my %t = %target; %t = ( %t, %source ); }, ruzam => sub { my %t = %target; while ( my($key, $value) = each %source) { # $target{$key} = $value <-- oops! $t{$key} = $value } }, }); __END__ Rate sleepyjay ruzam grandfather sleepyjay 905/s -- -58% -61% ruzam 2162/s 139% -- -8% grandfather 2349/s 160% 9% --

Back to Snippets Section

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (5)
As of 2014-07-26 11:49 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite superfluous repetitious redundant duplicative phrase is:









    Results (176 votes), past polls