http://www.perlmonks.org?node_id=21080

draco_iii has asked for the wisdom of the Perl Monks concerning the following question: (hashes)

How do I make all the values in %a with common keys in %b equal to %b's values?

Originally posted as a Categorized Question.

  • Comment on How do I make all the values in %a with common keys in %b equal to %b's values?

Replies are listed 'Best First'.
Re: How do I make all the values in %a with common keys in %b equal to %b's keys?
by vroom (His Eminence) on Jul 05, 2000 at 08:41 UTC
    Iterate through each key in %a. If %b contains the current hash key, set %a's value to %b's value for that key.
    foreach(keys %a){ $a{$_} = $b{$_} if exists $b{$_}; }
    Editor's note:
    Or, as merlyn has pointed out, hash slices can make you very happy...
    @a{keys %b} = values %b;

      The second answer may be incorrect. According to the question: we are to find all the matches between the keys in %a and %b, and if there is a match, assign the value of the matching element from %b into the corresponding element in %a.

      A hash slice won't work in this case, consider:

      my %a = ( a => 1, b => 2, c => 3, ); my %b = ( b => 4, d => 8, f => 12, ); @a{ keys %b } = values %b;

      Now, %a is:

      %a = ( a => 1, b => 4, c => 3, d => 8, f => 12, );

      Which is the incorrect answer, according to the question. If we use a hash slice, we'll be copying all the elements from %b into %a, regardless if there are any matches, or not.

Re: How do I make all the values in %a with common keys in %b equal to %b's keys?
by grinder (Bishop) on Aug 22, 2000 at 18:30 UTC
    Hash slices may make you unhappy. The above will introduce %b's keys into %a regardless of whether they existed in %a or not. Consider
    my %a = ( A => 1, B => 2, C => 3 ); my %b = ( A => 100, D => 200 ); @a{keys %b} = values %b; print( "$_ => $a{$_}\n" ) foreach( sort keys %a );
Re: How do I make all the values in %a with common keys in %b equal to %b's keys?
by CharlesClarkson (Curate) on Jun 11, 2001 at 13:10 UTC
    my @common = grep exists $a{$_}, keys %b; @a{@common} = @b{@common};
Re: How do I make all the values in %a with common keys in %b equal to %b's keys?
by cLive ;-) (Prior) on Mar 30, 2001 at 11:04 UTC
    Assuming %b has no null/empty/zero values:
    for (keys %a) { $a{$_} = $b{$_} || $a{$_}; }

      Here's another way to do that:

      foreach my $key (keys %a) { $a{$key} = $b{$key} if exists $b{$key}; }

      or

      exists $b{$_} and $a{$_} = $b{$_} for keys %a;
Re: How do I make all the values in %a with common keys in %b equal to %b's keys?
by Roy Johnson (Monsignor) on Nov 03, 2003 at 19:53 UTC
    CharlesClarkson's can be written without the use of a temp or slices:

    $a{$_} = $b{$_} for (grep exists $b{$_}, keys %a);

    which also benchmarks a little better. For clarity, I like vroom's solution.

    Note that if you know that one hash is much larger than the other, you will do better to iterate through the keys of the smaller hash and test exists against the larger.

Re: How do I make all the values in %a with common keys in %b equal to %b's keys?
by QM (Parson) on Nov 03, 2003 at 22:32 UTC
    How do I make all the values in %a with common keys in %b equal to %b's keys?
    Shouldn't that last keys be changed to values? Either that, or everyone has answered the wrong question.

    For the question asked, it seems this would work:

    $a{$_} = $_ for (grep exists $b{$_}, keys %a);
Re: How do I make all the values in %a with common keys in %b equal to %b's keys?
by grinder (Bishop) on Aug 22, 2000 at 18:33 UTC
    Continuing my answer... the example code will correctly update the key 'A', but it will also introduce the key 'D', which may not be what you expected, given the original question.