Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw

Concatenate anonymous hash ref

by wanna_code_perl (Pilgrim)
on Oct 14, 2008 at 16:45 UTC ( #717037=perlquestion: print w/replies, xml ) Need Help??
wanna_code_perl has asked for the wisdom of the Perl Monks concerning the following question:

Hello Monks,

What is the most elegant way to combine two hashes by reference? I basically want to do this:

$x = { foo => "abc" }; $x .= { bar => "def", baz => "ghi" }; # I want $x to be: # { foo => "abc", bar => "def", baz => "ghi" }

Obviously, the concatenation operator won't have the desired effect.

And I know I can manually concatenate the two hashes, with, say:

my $temp = { bar => "def", baz => "ghi" }; foreach my $key (keys %$temp) { $x->{$key} = $temp->{$key}; }

Overwriting values is expected and OK in my application.

However, is there a more elegant (and time/memory efficient) solution?

The hash refs are a return from a function. I want to concatenate the return from successive calls.

Update: Thanks for the good ideas! It turns out it is cleaner for me to just pass the reference to my helper functions, and let them modify it. I was trying to avoid the extra parameter, but looks like that will be the easiest to maintain in this case.

Replies are listed 'Best First'.
Re: Concatenate anonymous hash ref
by Corion (Pope) on Oct 14, 2008 at 16:49 UTC

    See Hash::Merge.

    Also, depending on what values you want to survive, you can use the following approaches:

    $x = { foo => "abc", from => 'x' }; $y = { bar => "def", baz => "ghi", from => 'y' }; my $merged_x = { %$y, %$x }; my $merged_y = { %$x, %$y };

    If you want to modify $x in-place, you can also use a hash slice:

    @{$x}{keys %$y} = values %$y; # Values in $y override values in $x
Re: Concatenate anonymous hash ref
by ikegami (Pope) on Oct 14, 2008 at 17:25 UTC

    "." is string concatenation. Not what you want.

    If you were dealing with hashes directly, you'd do

    %x = ( %x, bar => "def", baz => "ghi" );

    or better yet

    @x{qw( bar baz )} = ( "def", "ghi" );

    But you're dealing with references to hash, so you simply need to dereference first as per Dereferencing Syntax.

    %$x = ( %$x, bar => "def", baz => "ghi" );
    @$x{qw( bar baz )} = ( "def", "ghi" );

    Update: Ah shoot! I had @x[...] where I should have had @x{...}. Fixed.

      "." is string concatenation. Not what you want.

      But this is Perl. If you really, really want it, it can happen!

      use 5.010; use strict; use warnings; my $x = {foo => "abc"}; { package ChocolateSauce; use overload '.' => \&whipped_cream; sub whipped_cream { my ($adam, $eve) = @_[$_[2] ? (1, 0) : (0, 1)]; $$adam{$_} = $$eve{$_} for keys %$eve; $adam; } } bless $x => 'ChocolateSauce'; $x .= {bar => 'def', baz => 'ghi'}; while (my ($k, $v) = each %$x) { say "$k => $v"; } __END__ bar => def baz => ghi foo => abc
Re: Concatenate anonymous hash ref
by Thelonius (Priest) on Oct 14, 2008 at 20:55 UTC
    You can replace this little loop
    foreach my $key (keys %$temp) { $x->{$key} = $temp->{$key}; }
    @$x{keys %$temp} = values %$temp;

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://717037]
Approved by moritz
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (3)
As of 2018-04-22 06:50 GMT
Find Nodes?
    Voting Booth?