Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

How to loop through hash of hashes and add the values based on condition?

by Sami_R (Sexton)
on Jan 06, 2020 at 16:20 UTC ( [id://11111061]=perlquestion: print w/replies, xml ) Need Help??

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

Hi Monks,

Have hash of hashes need to loop through and add values of 'month' total values and day+week total values of all except for 'Sum'.

my $month_total = 0; my $day_week_total = 0; $VAR1 = { 'Adam' => { 'days' => 22, 'weeks' => 5, 'total' => 22 }, 'Keas' => { 'total' => 114, 'test' => 2, 'weeks' => 8, 'days' => 107, 'months' => 5 }, 'Tim' => { 'total' => 4, 'weeks' => 5, 'days' => 3, 'months' => 1 }, 'Sum' => { 'total' => 440, 'days' => 365, 'months' => 9 } };

Loop through the hash of hashes and add all the 'months' value except for the key 'Sum'. $month_total = 6 ( none for 'Adam' + 5 for 'Keas' + 1 for 'Tim' ) Loop through the hash of hashes and add all the values of 'days'+'weeks' except for the key 'Sum'. $day_week_total = 150 ( (22+5) for 'Adam' + (107+8) for 'Keas' + (3+5) for 'Tim' )

Expected output: $month_total = 6; $day_week_total = 150;

Dear Monks, please give me a direction to achieve this. Thank you so much

  • Comment on How to loop through hash of hashes and add the values based on condition?
  • Download Code

Replies are listed 'Best First'.
Re: How to loop through hash of hashes and add the values based on condition?
by Fletch (Bishop) on Jan 06, 2020 at 16:37 UTC

    See "Access and Printing of a HASH OF HASHES" in perldsc. Use next to skip the top level key if it's eq q{Sum}.

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.

Re: How to loop through hash of hashes and add the values based on condition?
by tybalt89 (Monsignor) on Jan 06, 2020 at 21:16 UTC
    #!/usr/bin/perl use strict; # https://perlmonks.org/?node_id=11111061 use warnings; my $month_total = 0; my $day_week_total = 0; my $VAR1 = { 'Adam' => { 'days' => 22, 'weeks' => 5, 'total' => 22 }, 'Keas' => { 'total' => 114, 'test' => 2, 'weeks' => 8, 'days' => 107, 'months' => 5 }, 'Tim' => { 'total' => 4, 'weeks' => 5, 'days' => 3, 'months' => 1 }, 'Sum' => { 'total' => 440, 'days' => 365, 'months' => 9 } }; for my $key ( grep $_ ne 'Sum', keys %$VAR1 ) { $month_total += ($VAR1->{$key}{months} // 0); $day_week_total += $VAR1->{$key}{days} + $VAR1->{$key}{weeks}; } print "month_total = $month_total day_week_total = $day_week_total\n";
      Hi Tybalt89,

      Thank you so much for the different approach.

Re: How to loop through hash of hashes and add the values based on condition?
by Anonymous Monk on Jan 06, 2020 at 16:38 UTC
    What did you try?
      Thanks.

      Attached the code which've tried ...

      for $name ( sort keys %{$VAR1} ) { for $calen ( sort keys %{ $VAR1{$name} } ) { for $value ( sort keys %{ $VAR1{$name}{$calen} } ) { if ( $VAR1{$name} ne ‘Sum’ ) { if ( ($VAR1{$name}{$calen} eq ‘days’) || ($VAR1{$name} +{$calen} eq ‘weeks’) ){ $day_week_total += $VAR1{$name}{$calen}{$value} if +($VAR1{$name}{$calen}{$value}); } elsif ( ($VAR1{$name}{$calen} eq ‘months’) ){ $month_total += $VAR1{$name}{$calen}{$value} if($V +AR1{$name}{$calen}{$value}); } } } } print “day_tot: $day_week_total — mon_tot: $month_total“;

        First, that's not your code, because there's a missing } and you have smartquotes instead of real quotes, so it wouldn't compile. I am otherwise ignoring those errors for now as probably an artifact of however you entered your post into the forum. As Fletch said, perldsc will help you; use warnings; use strict; will even help you find which variable you aren't referencing: Global symbol "%VAR1" requires explicit package name (did you forget to declare "my %VAR1"?) at C:\Users\....pl line 35.. Looking, your syntax $VAR1{$name} is looking up the $name key of the non-existent %VAR1 hash; you really want to look at the $name key of the $VAR1 hashref using the syntax $VAR1->{$name} -- and have multiple similar instances throughout. Also, Basic debugging checklist will help you debug your code; strict, warnings, and print statements easily found that problem. Try again, and if you're still having problems, post the full code (including example data and executable code in the same post), and explain the changes that you have made, why you made them.

        edit: that will only fix down to the $value loop, where you are trying to extract the $value from the keys of the non-existent subhash of $VAR1->{$name}{$calen}: that is not a hashref, but a scalar value, so you don't need to take the keys or loop over it. With that hint, I'll let you continue to figure out that portion, as well (there are more problems after that; I'm just stopping there for now)

        You can simplify all the dereferencing if you use a while loop with each rather than a for loop. With this method, you cannot sort the keys, but in your case, that is OK.
        use strict; use warnings; use Test::More tests => 2; my $month_total = 0; my $day_week_total = 0; my $VAR1 = { 'Adam' => { 'days' => 22, 'weeks' => 5, 'total' => 22 }, 'Keas' => { 'total' => 114, 'test' => 2, 'weeks' => 8, 'days' => 107, 'months' => 5 }, 'Tim' => { 'total' => 4, 'weeks' => 5, 'days' => 3, 'months' => 1 }, 'Sum' => { 'total' => 440, 'days' => 365, 'months' => 9 } }; while (my ($name, $hash) = each %$VAR1) { next if $name eq 'Sum'; if (exists $hash->{months}) { $month_total += $hash->{months}; } if (exists $hash->{days} and exists $hash->{weeks}) { $day_week_total += ($hash->{days} + $hash->{weeks}); } } ok($month_total == 6, 'month_total'); ok($day_week_total == 150, 'day_week_total'); OUTPUT: 1..2 ok 1 - month_total ok 2 - day_week_total
        Bill

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://11111061]
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others sharing their wisdom with the Monastery: (3)
As of 2024-04-20 15:16 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found