1

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?

chrisrhyno2003
  • 3,906
  • 8
  • 53
  • 102

2 Answers2

1

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.

Dave Cross
  • 68,119
  • 3
  • 51
  • 97
0

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";
    }
}
Mohit
  • 608
  • 4
  • 19
  • Weirdly, my local box was throwing me errors. I'll try updating my perl version just in case. – chrisrhyno2003 Oct 26 '17 at 04:59
  • Try running this code i pasted to confirm that it's your perl version that is creating issues. You could also try running in https://www.tutorialspoint.com/execute_perl_online.php – Mohit Oct 26 '17 at 05:01
  • As your code was not giving desired output for me also – Mohit Oct 26 '17 at 05:02
  • Your code now gives me the desired results. Was there something I was missing? – chrisrhyno2003 Oct 26 '17 at 05:05
  • I hope issue was in this line- $hash2->{$accountId} where does accountid come from – Mohit Oct 26 '17 at 05:06
  • also the way of receiving params, you need to change them to hash – Mohit Oct 26 '17 at 05:08
  • Ah I see, I was under the assumption I can use the hashrefs the way they are and wasn't completely required to change them to a hash. – chrisrhyno2003 Oct 26 '17 at 05:09
  • *also the way of receiving params, you need to change them to hash* - No. He doesn't need to change that. Using hash references is a perfectly reasonable way to write this code. – Dave Cross Oct 30 '17 at 12:30
  • @chrisrhyno2003: *I was under the assumption I can use the hashrefs the way they are and wasn't completely required to change them to a hash." - You are correct. Your original code was fine. – Dave Cross Oct 30 '17 at 12:30