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

Hi there. I'm trying to merge two hashes, which may contain some of the same keys, to produce another hash with the values summed.

For example, if both hashes looked like this:

%Hash1 key 1 => '1' key 15 => '3' key 150 => '1'
%Hash2 key 1 => '1' key 15 => '1' key 140 => '1'

I would like the final hash to look like this:

%CombinedHash key 1 => '2' key 15 => '4' key 140 => '1' key 150 => '1'

I hope this makes sense? I have included a fragment of code that does not work properly, below - upon testing I've found that it doesn't sum the values correctly, just a '1' if the key/val pair was not merged and a '2' if it was. I suppose I could do something with a loop to iterate over each hash in turn? I'd really appreciate any help with this.

my %muthash = ( key1 => '1', key15 => '3', key150 => '1', ); my %copyhash ( key1 => '1', key15 => '1', key140 => '1', ); my %mergedhash; %mergedhash = map {$_=> $muthash{$_} + $copyhash{$_} } (keys %muthash, +keys %copyhash);

This is just where I'd like to put the data afterwards - included for reference.

my $fileoutput = $name." COMB".".csv"; open (OUTPUT,">Input/$fileoutput") or die "Could not open output file\ +n"; foreach my $gene (keys %mergedhash) { print OUTPUT "$gene",",","$mergedhash{$gene}","\n"; } close (OUTPUT);

UPDATE: Thanks for your input guys! It turns out I'm a flipping idiot and wasn't populating my hashes properly in the first place. You're all heroes though, and iterating through your solutions has taught me things. Thanks again!

Replies are listed 'Best First'.
Re: Merging two hashes, keeping keys unique but adding values if necessary
by LanX (Saint) on Jun 04, 2014 at 15:55 UTC
    If I understand your problem correctly (adding values of "same" keys) , your map ² works as expected!

    DB<107> \%result => { key1 => 2, key140 => 1, key15 => 4, key150 => 1 }

    If you still believe its wrong please show working code¹ and point out whats missing.

    Cheers Rolf

    (addicted to the Perl Programming Language)

    ¹) there is at least one = missing

    ²) Well this (keys %muthash,keys %copyhash) will produce overhead cause it's not a unique list, anyway map still works.)

Re: Merging two hashes, keeping keys unique but adding values if necessary
by LanX (Saint) on Jun 04, 2014 at 16:24 UTC
    I still can't see an error in your approach, but simply adding to an empty hash looks simpler, is easier to maintain and likely more time efficient. :)

    DB<103> %copyhash=( key1 => '1', key15 => '1', key140 => '1', ); => ("key1", 1, "key15", 1, "key140", 1) DB<104> %muthash = ( key1 => '1', key15 => '3', key150 => '1', ); => ("key1", 1, "key15", 3, "key150", 1) DB<105> $mergedhash{$_} += $muthash{$_} for keys %muthash => "" DB<106> $mergedhash{$_} += $copyhash{$_} for keys %copyhash => "" DB<107> \%mergedhash => { key1 => 2, key140 => 1, key15 => 4, key150 => 1 }

    Cheers Rolf

    (addicted to the Perl Programming Language)

Re: Merging two hashes, keeping keys unique but adding values if necessary
by tangent (Parson) on Jun 04, 2014 at 18:41 UTC
    Update: Just realized this is the very same as LanX above - DB<105> etc. was confusing me.

    This may help, and will allow you to merge as many hashes as you wish:

    use strict; use warnings; use Data::Dumper; my %hash1 = ( "key1" => 1, "key15" => 3, "key150" => 1 ); my %hash2 = ( "key1" => 1, "key15" => 1, "key140" => 1 ); my %merged; $merged{$_} += $hash1{$_} for keys %hash1; $merged{$_} += $hash2{$_} for keys %hash2; print Dumper(\%merged);
    Output:
    $VAR1 = { 'key15' => 4, 'key140' => 1, 'key1' => 2, 'key150' => 1 };
Re: Merging two hashes, keeping keys unique but adding values if necessary
by baxy77bax (Deacon) on Jun 04, 2014 at 15:59 UTC
    sorry wrong code

    update : i appologize por posting accidently into the wrong window

    well you were almost there. here is a version utilizing your approach:

    use strict; use Data::Dumper; %muthash = ( key1 => '1', key15 => '3', key150 => '1', ); %copyhash =( key1 => '1', key15 => '1', key140 => '1', ); %mergedhash = (); %mergedhash = map {$_=> $muthash{$_} + $copyhash{$_}; } (keys %muthash +, keys %copyhash); print Dumper(\%mergedhash);
    however, if you are biginner, do not go exploring functions like map until you master "for", "while" and "foreach" loop. Thus equivalent to your proposed solution is :
    my %muthash = ( "key1" => 1, "key15" => 3, "key150" => 1 ); my %copyhash = ( "key1" => 1, "key15" => 1, "key140" => 1 ); my %mergedhash; foreach (keys %muthash){ $mergedhash{$_} = $muthash{$_}+ $copyhash{$_}; } foreach (keys %copyhash){ $mergedhash{$_} = $muthash{$_}+ $copyhash{$_} unless defined $mergedha +sh{$_}; } print Dumper(\%mergedhash);
    cheers
      you are using the values from one hash as keys for the other one !?!

      update

      and in your updated version the key/values unique to the %copyhash (like key140 ) will be missing.

      Cheers Rolf

      (addicted to the Perl Programming Language)

Re: Merging two hashes, keeping keys unique but adding values if necessary
by perlfan (Parson) on Jun 05, 2014 at 13:15 UTC
    If you take your hashes to actually be matrixes to be added, then you can also think of some other solutions representing them instead as arrays of arrays. The only issue here is that this is not an efficient representation of the data if your matrixes end up being sparse.