in reply to Re: Merge hash into another hash
in thread Merge hash into another hash

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!

Replies are listed 'Best First'.
Re^3: Merge hash into another hash
by SleepyJay (Beadle) on Jul 16, 2009 at 23:05 UTC
    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.

      Hi, let me try to explain with my limited knowledge of perl's internal behaviour ;o)

      Your solution converts %target and %source into flat lists, combines it to one list and assigns that list to %target...

      Grandfather's solution only inserts the key-value pairs from %source into %target, overwriting already existing pairs.

      This is less expensive than converting into lists and reassigning these lists.

      I tried a benchmark which shows that Grandfather's solution is faster than yours.

      I have to admit, that - until this post - I preferred and used the way you presented (mainly because of readability), but now I have to reconsider ;o)

      #!/usr/bin/perl # vim: set ts=4 sw=4 et sta: use strict; use warnings; use Benchmark qw( cmpthese ); my %target; my %source; ## prefill @target{'aa'..'zz' } = 'aa' .. 'zz'; @source{'ww'..'yy', 1..100} = ( 'ww'..'yy', 1..100 ); cmpthese( -1, { grandfather => sub { my %t = %target; @t{keys %source} = values %source; }, sleepyjay => sub { my %t = %target; %t = ( %t, %source ); }, }); __END__ Rate sleepyjay grandfather sleepyjay 598/s -- -62% grandfather 1585/s 165% -- Rate sleepyjay grandfather sleepyjay 649/s -- -62% grandfather 1706/s 163% --