stupidius has asked for the wisdom of the Perl Monks concerning the following question:

I have a hash: %hash1, it has 5 keys, each with one value.

I want to change 2 of the key's values in that hash.

The new values are in %hash2.

%hash2 only has 2 keys, so how can I update %hash1 with %hash2?

I've literally been at this for over 2 hours and still can't get it working. I must be missing something here. Help!

Replies are listed 'Best First'.
Re: update a hash with a hash
by friedo (Prior) on Jul 15, 2004 at 02:26 UTC
    Here's a simple way to do it with a loop:

    $hash1{$_} = $hash2{$_} for keys %hash2;

    You can also use a hash slice:

    @hash1{keys %hash2} = values %hash2;
Re: update a hash with a hash
by rjbs (Pilgrim) on Jul 15, 2004 at 02:33 UTC
    It's not as efficient as friedo's solution, but I generally find myself writing:
    %hash1 = (%hash1, %hash2);
    In other words, "hash1 is itself, plus all of hash2, using hash2's values where they conflict."
    rjbs
Re: update a hash with a hash
by Enlil (Parson) on Jul 15, 2004 at 02:35 UTC
Re: update a hash with a hash
by beable (Friar) on Jul 15, 2004 at 03:05 UTC
    Here is a nice simple easy-to-understand way to do it:

    # update hash1 with the stuff in hash2 foreach my $key (keys %hash2) { $hash1{$key} = $hash2{$key}; }
Re: update a hash with a hash
by NetWallah (Canon) on Jul 15, 2004 at 04:24 UTC
    And here is YET another way:

    (And easiest to understand, to my way of thinking) -

    while (my ($k,$v) = each %hash2){ $hash1{$k} = $v; }

        Earth first! (We'll rob the other planets later)

Re: update a hash with a hash
by pearlie (Sexton) on Jul 15, 2004 at 07:37 UTC
    hi the following code must work as far as i understood the question. I assumed that the 2 keys for which values have to be changed are the same as keys in the second hash:
    #!/usr/bin/perl my %hash1 = ( key1 => val1, key2 => val2, key3 => val3, key4 => val4, key5 => val5); my %hash2 = ( key1 => xxxval1, key2 => xxxval2); out:foreach my $key (keys %hash1) { foreach my $inkey (keys %hash2) { if($key eq $inkey) { $hash1{$key} = $hash2{$inkey}; next out; } } }
    hope it solves your problem.

    janitored by ybiC: Balanced <code> tags around codeblock

      You should really use <code> </code> tags around your code. It'll look a lot better, like this:
      #!/usr/bin/perl use strict; use warnings; use Data::Dumper; my %hash1 = ( key1 => "val1", key2 => "val2", key3 => "val3", key4 => "val4", key5 => "val5"); my %hash2 = ( key1 => "xxxval1", key2 => "xxxval2"); print Dumper(%hash1), "\n"; out:foreach my $key (keys %hash1) { foreach my $inkey (keys %hash2) { if($key eq $inkey) { $hash1{$key} = $hash2{$inkey}; next out; } } } print Dumper %hash1; __END__

      However, I put it to you that the nested foreach loops are unnecessary, and that this does the same thing:

      #!/usr/bin/perl use strict; use warnings; use Data::Dumper; my %hash1 = ( key1 => "val1", key2 => "val2", key3 => "val3", key4 => "val4", key5 => "val5"); my %hash2 = ( key1 => "xxxval1", key2 => "xxxval2"); print Dumper(%hash1), "\n"; foreach my $inkey (keys %hash2) { if(exists $hash1{$inkey}) { $hash1{$inkey} = $hash2{$inkey}; } } print Dumper %hash1; __END__

      Because hey! It's a hash! There's no need to loop over the keys to see what's in it.