in reply to Re: Simplify HoH code
in thread Simplify HoH code

Firs thanks for quick reply. Yes , initially i had if else instead of given/when . I switched to given/when later maybe bad choice :( i will use perltidy for formatting. Actual content will be in that format. Ok to have hash there too insteadof bunch of variables but considering HoH loops & nested ifs, Not sure to check with this new hash against HoH second loop. i added updated script with few more variables and if checks and comment on exit/print information from perltidy output:
#!/usr/bin/perl use warnings; use strict; use feature "switch"; my %Hash = (); $Hash{"FEB"}{"W1"} = 10.14; $Hash{"FEB"}{"W2"} = 11.22; $Hash{"MAR"}{"W1"} = 33.17; $Hash{"MAR"}{"W2"} = 44.44; $Hash{"APR"}{"W1"} = 55.00; $Hash{"APR"}{"W2"} = 66.66; my $FEB_L1_W1 = 11; my $FEB_U1_W1 = 12.05; my $FEB_L1_W2 = 13.06; my $FEB_U1_W2 = 13.06; my $APR_L1_W1 = 1; my $APR_U1_W1 = 20; my $APR_L1_W2 = 33; my $APR_U1_W2 = 13.02; my $MAR_L1_W1 = -12.05; my $MAR_U1_W1 = -14.0; my $MAR_L1_W2 = 22.0; my $MAR_U1_W2 = -13.02; for my $month ( keys %Hash ) { print "$month: "; for my $week ( keys %{ $Hash{$month} } ) { print "$week=$Hash{$month}{$week} \n"; # Did you mean to hashloop for values here instead of hardcode +d variable names? if ( $month eq "FEB" ) { if ( $week eq "W1" ) { if ( ( $FEB_L1_W1 <= $Hash{$month}{$week} ) and ( $Hash{$month}{$week} <= $FEB_U1_W1 ) ) { print "month $month has f status for $week: $Hash{$month}{$week}\n"; } else { print "error: print something"; } } elsif ( $week eq "W2" ) { if ( ( $FEB_L1_W2 <= $Hash{$month}{$week} ) and ( $Hash{$month}{$week} <= $FEB_U1_W2 ) ) { print "month $month has f status for $week: $Hash{$month}{$week}\n"; } else { # print error key/value : $month $Hash{$month} $Hash{$mon +th}{$week} # get exit code } } } if ( $month eq "MAR" ) { if ( $week eq "W1" ) { if ( ( $MAR_L1_W1 <= $Hash{$month}{$week} ) and ( $Hash{$month}{$week} <= $MAR_U1_W1 ) ) { print "month $month has f status for $week: $Hash{$month}{$week}\n"; } else { # print error key/value : $month $Hash{$month} $Hash{$mon +th}{$week} # get exit code } } elsif ( $week eq "W2" ) { if ( ( $MAR_L1_W2 <= $Hash{$month}{$week} ) and ( $Hash{$month}{$week} <= $MAR_U1_W2 ) ) { print "month $month has f status for $week: $Hash{$month}{$week}\n"; } else { # print error key/value : $month $Hash{$month} $Hash{$mon +th}{$week} # get exit code } } } } }

Replies are listed 'Best First'.
Re^3: Simplify HoH code
by haukex (Archbishop) on Dec 03, 2017 at 11:51 UTC

    Do I understand correctly that the variables named *_L1_* are lower limits and *_U1_* are upper limits? Although pme has shown code very similar to what I was thinking, the key thing to note is that you can restructure your $FEB_L1_W1 variables into a hash, and then see the similarity in the data structures (Data::Dumper or Data::Dump can also be helpful here).

    my %months = ( FEB => { W1 => 11.14, W2 => 11.22, }, MAR => { W1 => 33.17, W2 => 44.44, }, APR => { W1 => 55.00, W2 => 66.66, }, ); my %limits = ( FEB => { W1 => { L1 => 11, U1 => 12.05 }, W2 => { L1 => 13.06, U1 => 13.06 }, }, APR => { W1 => { L1 => 1, U1 => 20 }, W2 => { L1 => 33, U1 => 13.02 }, }, MAR => { W1 => { L1 => -12.05, U1 => -14.0 }, W2 => { L1 => 22.0, U1 => -13.02 }, }, );

    And then notice you can create loops to loop over both at the same time, like in the following. Note I've made a few assumptions, like that limits for a certain month may not exist, but when they do, both the keys U1 and L1 are defined. If your input data varies, you may have to adjust this.

    for my $mon ( sort keys %months ) { for my $week ( sort keys %{ $months{$mon} } ) { if ( exists $limits{$mon} && exists $limits{$mon}{$week} ) { my $value = $months{$mon}{$week}; my $upper = $limits{$mon}{$week}{U1}; my $lower = $limits{$mon}{$week}{L1}; printf "%6.2f <= %6.2f <= %6.2f - ", $lower, $value, $upper; if ( $value >= $lower && $value <= $upper ) { print "OK\n"; } else { print "NOT ok\n"; } } else { warn "No limits for month $mon / week $week\n" } } }

    Which gives the following output. Note I tweaked the input slightly to give at least one "OK" output.

    1.00 <= 55.00 <= 20.00 - NOT ok 33.00 <= 66.66 <= 13.02 - NOT ok 11.00 <= 11.14 <= 12.05 - OK 13.06 <= 11.22 <= 13.06 - NOT ok -12.05 <= 33.17 <= -14.00 - NOT ok 22.00 <= 44.44 <= -13.02 - NOT ok
      Hi, Nice one. missed the logic on getting values without looping when i have another hash. Thanks haukex & pme .