Perl - Merge hash containing duplicate keys

2019-08-18 06:37发布

问题:

I have two hashes which can contain the same keys. I am trying to merge the two hashes in such a way that if the key exists in both the hashes, I want to add the values in the respective hashes.

my %hash1= ();
$hash1{'apple'} = 10;
$hash1{'banana'} = 15;
$hash1{'kiwi'} = 20;

my %sourceHash = ();
$sourceHash{'apple'} = 12;
$sourceHash{'orange'} = 13;
$sourceHash{'banana'} = 5;


mergeHash(\%hash1, \%sourceHash);


sub mergeHash {
    my $hash1 = shift;
    my $hash2 = shift;

    foreach my $key (keys %{$hash1})
    {
        if (exists $hash2->{$key}) {
            ${hash2}->{$key} = $hash1->{$key} + $hash2->{$key};
        } else {
            ${hash2}->{$key} = $hash1->{$key};
        }
    }
}

I expect the result of hash1 to be

hash1{'apple'} = 22;
hash1{'orange'} = 13;
hash1{'banana'} = 20;
hash1{'kiwi'} = 20;

But I get an exception saying Can't modify constant item in scalar assignment. What am I doing wrong?

回答1:

PFB the updated code with proper syntax and it is giving the desired output also:

my %hash1= ();
$hash1{'apple'} = 10;
$hash1{'banana'} = 15;
$hash1{'kiwi'} = 20;

my %sourceHash = ();
$sourceHash{'apple'} = 12;
$sourceHash{'orange'} = 13;
$sourceHash{'banana'} = 5;

mergeHash(\%hash1, \%sourceHash);


sub mergeHash {
    my $param1 = shift;
    my %hash1 = %$param1;
    my $param2 = shift;
    my %hash2 = %$param2;

    foreach my $key (keys %hash1){
        if(exists $hash2{$key}){
            print "coming in here for $hash1->{$key} \n";
            $hash2{$key} = $hash1{$key} + $hash2{$key};
        }
        else{
            $hash2{$key} = $hash1{$key};
        }
    }
    showHash(\%hash2);
}
sub showHash{

    my $param = shift;
    my %param_hash = %$param;


    for my $fruit (keys %param_hash) {
    print "The value of '$fruit' is $param_hash{$fruit}\n";
    }
}


回答2:

You say:

I expect the result of hash1 to be

hash1{'apple'} = 22;
hash1{'orange'} = 13;
hash1{'banana'} = 20;
hash1{'kiwi'} = 20;

But in your code, you iterate over the keys of $hash1:

 foreach my $key (keys %{$hash1})

And alter the contents of $hash2:

if (exists $hash2->{$key}) {
    ${hash2}->{$key} = $hash1->{$key} + $hash2->{$key};
} else {
    ${hash2}->{$key} = $hash1->{$key};
}

So you shouldn't expect to see any changes in $hash1, you are changing $hash2.

I added this to your code:

use Data::Dumper;

And, after the call to mergeHash():

print Dumper \%hash1, \%sourceHash;

I got this output:

$VAR1 = {
          'apple' => 10,
          'kiwi' => 20,
          'banana' => 15
        };
$VAR2 = {
          'orange' => 13,
          'banana' => 20,
          'kiwi' => 20,
          'apple' => 22
        };

So your code is doing what you wanted. It's just doing it to the other hash. There's nothing wrong with your code.



标签: perl hash