Tincho Tincho - 4 months ago 29
Perl Question

how to add multiple values from multiple hashes with same key (perl)

Hello people im trying to add multiple values from multiple hashes with same key.

And this is the result of scheme that I want acomplish.

HASH1 => {
'2016-07-01' => { 'val1' => '7', 'val2' => '9', },
'2016-07-02' => { 'val1' => '10', 'val2' => '6', } }
HASH2 => {
'2016-07-01' => { 'val1' => '8', 'val2' => '4', },
'2016-07-03' => { 'val1' => '3', 'val2' => '2', } }

HASH3 => {
'2016-07-01' => { 'val1' => '6', 'val2' => '5', },
'2016-07-02' => { 'val1' => '1', 'val2' => '2', },
'2016-07-04' => { 'val1' => '4', 'val2' => '2', } }

OUTPUT HASH => {
'2016-07-01' => { 'val1' => '21', 'val2' => '18', },
'2016-07-02' => { 'val1' => '11', 'val2' => '8', },
'2016-07-03' => { 'val1' => '3', 'val2' => '2', },
'2016-07-04' => { 'val1' => '4', 'val2' => '2', }, }


Im trying pushing duplicate keys to an array to identify each one, then add values.
This i'm trying is for compare 2 hashes, but i want make it for multiple hashes.

my @common = ();
foreach (keys %HASH1) {
push(@common, $_) if exists $HASH2{$_};
}
foreach my $DUP_KEY (@common){
my $v1 = $HASH1{$DUP_KEY}{'val1'} + $HASH2{$DUP_KEY}{'val1'};
my $v2 = $HASH1{$DUP_KEY}{'val2'} + $HASH2{$DUP_KEY}{'val2'};
$HASH1{$DUP_KEY}{'val1'} = $v1;
$HASH1{$DUP_KEY}{'val2'} = $v2;
}

my %OUT_HASH = (%HASH1, %HASH2);


foreach my $key (keys %OUT_HASH) {push(@ARR, $key);}
foreach (sort @ARR) {push(@ARR_CLEAN, $_);
}


but the result is not as expected, because im getting only the duplicates keys only.

someone would be so kind as to help me? thank you!

Answer

To sum up the hashes of hashes, loop over all the hashes, over their first keys (here the date), then over the second key (here the value). Sum up the numbers in a new hash.

I'd move the code to sum the values to its own sub for clarity, then pass it the references of the hashes you want to sum up.

use strict; 
use warnings;

sub sum {
    my %sums;
    foreach my $hash (@_) {
        foreach my $date (keys %{$hash}) {
            foreach my $val (keys %{$$hash{$date}}) {
                $sums{$date}{$val} += $$hash{$date}{$val};
            }
        }
    }
    return %sums;
}


my %HASH1 = (
    '2016-07-01' => {'val1' => '7', 'val2' => '9'}, 
    '2016-07-02' => {'val1' => '10', 'val2' => '6'}
);
my %HASH2 = (
    '2016-07-01' => {'val1' => '8', 'val2' => '4'}, 
    '2016-07-03' => {'val1' => '3', 'val2' => '2'}
);
my %HASH3 = ( 
    '2016-07-01' => {'val1' => '6', 'val2' => '5'}, 
    '2016-07-02' => {'val1' => '1', 'val2' => '6'}, 
    '2016-07-04' => {'val1' => '4', 'val2' => '2'} 
);

my %sums = sum(\%HASH1, \%HASH2, \%HASH3);
foreach my $date (sort keys %sums) {
    print "$date\n";
    foreach my $val (keys %{$sums{$date}}) {
        print "    $val: $sums{$date}{$val}\n";
    }
}