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

I want to replace the value of one hash with the value of a second hash when there is a match value(hash1)- key(hash2).
my %hash1 = ( 700200 => '523235', 700204 => '523221', ); my %hash2 = ( 523235 => 'Title1', 523221 => 'Title2', );
#Result: ideally the change will happen in hash1, but
my $value1; foreach my $key1 (keys(%hash1)) { $value1 = $hash1{key1}; foreach my $key2 (keys (%hash2)) { if ($value1 eq $key2){ $hash3{$key1}= $hash2{$key2}; } } } print Dumper \%hash3; #this should be the expected result $VAR1 = { 700200 => 'Title1', 700204 => 'Title2', };
My code does not work at all, only return an empty hash
any help? Thanks!

Replies are listed 'Best First'.
Re: Replace the value of a hash
by dragonchild (Archbishop) on Apr 01, 2004 at 22:26 UTC
    foreach my $k (keys %hash1) { next unless exists $hash2{$hash1{$k}}; $hash1{$k} = $hash2{$hash1{$k}}; }

    ------
    We are the carpenters and bricklayers of the Information Age.

    Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - flyingmoose

Re: Replace the value of a hash
by Roy Johnson (Monsignor) on Apr 01, 2004 at 23:21 UTC
    values returns lvalues! You don't have to use keys to modify them (but you do have to get them aliased). This is way cool.
    for (values %hash1) { $_ = $hash2{$_} if exists $hash2{$_}; }

    The PerlMonk tr/// Advocate
Re: Replace the value of a hash
by duff (Parson) on Apr 01, 2004 at 22:27 UTC

    Since the values of your first hash are keys into your second hash, you don't need to do so much looping:

    for my $k1 (keys %hash1) { my $k2 = $hash1{$k1}; $hash1{$k1} = $hash2{$k2} if exists $hash2{$k2}; }
Re: Replace the value of a hash
by Anonymous Monk on Apr 01, 2004 at 22:30 UTC
    I Found the error, a missing $ sign in line
    $value1 = $hash1{key1};. I am using use strict;, how come it did not detect that?
    If there any other way to optimize my code?. thanks
      Stricture didn't catch it because it isn't an error. Perl does a nifty bit of DWIMery when you use a bareword as a hash key and just uses the string as a key, so you're creating a key called "key1".
      Thank you monks for giving me a better way to code it!
Re: Replace the value of a hash
by ambrus (Abbot) on Apr 02, 2004 at 20:19 UTC

    Let me recommend a functional-programmer's way:

    @hash1{keys %hash1}= @hash2{values %hash1};
      #!/usr/bin/perl use Data::Dumper; %hash1 = (a=>1,b=>2,c=>3); %hash2 = (1=>'A',2=>'B'); @hash3{keys %hash1}= @hash2{values %hash1}; #defined $hash3{$_} or delete $hash3{$_} for keys %hash3; print Dumper \%hash3; __END__ $VAR1 = { 'c' => undef, 'a' => 'A', 'b' => 'B' };

      I like this technique, but it leaves undef values if hash1 don't fully match the keys of hash2. The commented out line cleans up the undef, but if you have to resort to that whats the point. (I note also that the OP was creating a new hash, while most solutions so far modify the first hash.)

      qq

        Yes, that's true.

        Then, if you need a solution that will give you

        +{ 'b' => 'B', 'a' => 'A', 'c' => 3 };

        from the above data, the best is probably a straightforward solution like

        while (my ($key, $val)= each %hash1) { exists $hash2{$val} and $hash1{$key}= $hash2{$val}; }

        As this

        { my %thash= (map (($_,$_), values %hash1), %hash2); @hash3{keys %hash1}= @thash{values %hash1}; }

        is not only difficult to read, but also inefficent depending on your data.

Re: Replace the value of a hash
by ambrus (Abbot) on May 06, 2008 at 15:33 UTC