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

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.

Comment on Concatenate anonymous hash ref
Select or Download Code
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 (Curate) on Oct 14, 2008 at 20:55 UTC
    You can replace this little loop
    foreach my $key (keys %$temp) { $x->{$key} = $temp->{$key}; }
    with
    @$x{keys %$temp} = values %$temp;

Log In?
Username:
Password:

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

How do I use this? | Other CB clients
Other Users?
Others exploiting the Monastery: (10)
As of 2014-08-20 16:21 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The best computer themed movie is:











    Results (118 votes), past polls