Dear all,

Thanks a lot for the codes various people which all work perfectly!! I have 
also discover some useful functions (eval and state) which can also be very 
helpful for this kind of data.

In the light of this, my dataset got more complicated, now there are 3 layers 
of hashes and I need now to calculate across those hashes for each name, 
I have tried to apply some of the code structure which were kindly provided and 
worked well for my first question, although as the data structure is now more 
complicated and I need to assess the data accross hashes makes it more complex 
and I din’t manage to get  a solution for this. Again, any help would be 
greatly appreciated.
##############
this is the dataset  now
$VAR1 = {
          '100 ' => {
                      'y' => {
                               '1' => 88,
                               '3' => 89,
                               '5' => 99
                             },
                      'x' => {
                               '1' => 97,
                               '3' => 117,
                               '5' => 107
                             },
                      'z' => {
                               '1' => 95,
                               '3' => 97,
                               '5' => 94
                             }
                    },
          '101 ' => {
                      'y' => {
                               '1' => 188,
                               '3' => 189,
                               '5' => 199
                             },
                      'x' => {
                               '1' => 197,
                               '3' => 1117,
                               '5' => 1107
                             },
                      'z' => {
                               '1' => 195,
                               '3' => 197,
                               '5' => 194
                             }
                    }
        };

########################
For each $name (100 and 101)- there are 3 levels, x, y and z -Times are 1,3,5 
for all datasets, across x, y and z .
What needs to be calculated now with this more complex structure,  is  for each 
name, a calculation across the 3 hashes, for the 3 times.

for 100:
first line : no action
second line : should reflect the difference between time 3 and time 1 across 
x,y and z (x3-x1)+(y3-y1)+(z3-z1)
time :3 - 1 =2, 
value: calculation:  x (value 3(117)-value 1(97) + y (value 3 (89)) - value 1 
(88)) + z (value 3 (97) - value 1 (95))
total should be : 117-97 + 89-88 +97-95 =13 
third line: should reflect difference between time 5 and time 3 AND time 5 and 
time 1
time : 5-3, and 5-1
value: calculation: difference between time 5 and time 3 : x (-value5 (107) - 
value 3(117)) + y (value5 (99)- value 3 (89)) + z (value 5 (94) - value 3 (97) 
) = -3 total
                    difference between time 5 and time 1 : x (-value5 (107) - 
value 1(97)) + y (value5 (99)- value 1 (88)) + z (value 5 (94) - value 1 (95) ) 
= 20 total

#######################
my partial code,
#!/usr/local/bin/perl
use strict;
use warnings;
use feature 'state';
 
use Data::Dumper qw(Dumper);
my %hall;

$hall{"100 "}{'x'}{1}   = 97;
$hall{"100 "}{'x'}{3}    = 117;
$hall{"100 "}{'x'}{5}    = 107;
$hall{"100 "}{'y'}{1}   = 88;
$hall{"100 "}{'y'}{3}  = 89;
$hall{"100 "}{'y'}{5}  = 99;
$hall{"100 "}{'z'}{1}  = 95;
 $hall{"100 "}{'z'}{3}  = 97;
 $hall{"100 "}{'z'}{5}  = 94;
$hall{"101 "}{'x'}{1}   = 197;
$hall{"101 "}{'x'}{3}    = 1117;
$hall{"101 "}{'x'}{5}    = 1107;
$hall{"101 "}{'y'}{1}   = 188;
$hall{"101 "}{'y'}{3}  = 189;
$hall{"101 "}{'y'}{5}  = 199;
$hall{"101 "}{'z'}{1}  = 195;
 $hall{"101 "}{'z'}{3}  = 197;
 $hall{"101 "}{'z'}{5}  = 194;
 
print Dumper \%hall;
print "----------------\n";

foreach  my $name ( sort keys %hall) {
print "name.$name\n";
    foreach  my $subject (sort keys %{ $hall{$name} }) {
print "suject.$subject\n";

        foreach  my $values  ( sort  keys %{ $hall{$name}{$subject}}) {
        state ($lgrade,$lsubject,$lname,$ltimes);

       my $grade = $hall{$name}{$subject}; 
print "grade is .$grade\n"; # this is not working and gives a reference!
        my $times = $hall{$name}{$subject}{$values};
print "time is .$times\n";
      
        if (eval { $lgrade and $lname eq $name }) { 

            my ( $grade_diff, $times_diff) = ( $grade - $lgrade, 
$times-$ltimes);
            print "$name,  
$grade-$lgrade=$grade_diff:$name,$times-$ltimes=$times_diff \n";
        }




        ($ltimes, $lgrade,$lname) = ($times, $grade,$name);
    }
}
}

many thanks again for any tips/help,

Nathalie


>  Now, what I would like to achieve:
> > I want to make a calculation, in each $name (Peti and Foo), calculate:
> > for Peti:
> > first line : no action
> > second line -(minus) 1st line:
> > print subject 3-1=2, 89-88=1
> > third line - 2nd line:
> > print subject 4-3=1, 99-89=10
> >
> > for foo:
> > first line : no action
> > second line -(minus) 1st line:
> > print subject 2-1=2, 107-97=10

#!/usr/local/bin/perl
use strict;
use warnings;
use feature 'state';
 
use Data::Dumper qw(Dumper);
my %hall;

$hall{"100 "}{'x'}{1}   = 97;
$hall{"100 "}{'x'}{3}    = 117;
$hall{"100 "}{'x'}{5}    = 107;
$hall{"100 "}{'y'}{1}   = 88;
$hall{"100 "}{'y'}{3}  = 89;
$hall{"100 "}{'y'}{5}  = 99;
$hall{"100 "}{'z'}{1}  = 95;
 $hall{"100 "}{'z'}{3}  = 97;
 $hall{"100 "}{'z'}{5}  = 94;
$hall{"101 "}{'x'}{1}   = 197;
$hall{"101 "}{'x'}{3}    = 1117;
$hall{"101 "}{'x'}{5}    = 1107;
$hall{"101 "}{'y'}{1}   = 188;
$hall{"101 "}{'y'}{3}  = 189;
$hall{"101 "}{'y'}{5}  = 199;
$hall{"101 "}{'z'}{1}  = 195;
 $hall{"101 "}{'z'}{3}  = 197;
 $hall{"101 "}{'z'}{5}  = 194;
 
print Dumper \%hall;
print "----------------\n";
#my ($name,$subject,$values);
foreach  my $name ( sort keys %hall) {
print "name.$name\n";
    foreach  my $subject (sort keys %{ $hall{$name} }) {
print "suject.$subject\n";

        foreach  my $values  ( sort  keys %{ $hall{$name}{$subject}}) {
        state ($lgrade,$lsubject,$lname,$ltimes);

       my $grade = $hall{$name}{$subject}; 
print "grade is .$grade\n";
        my $times = $hall{$name}{$subject}{$values};
print "time is .$times\n";
      
        if (eval { $lgrade and $lname eq $name }) {

        #if (eval { $lsubject and $lgrade and $lname and $ltimes eq $name }) {

            my ( $grade_diff, $times_diff) = ( $grade - $lgrade, 
$times-$ltimes);
            print "$name,  
$grade-$lgrade=$grade_diff:$name,$times-$ltimes=$times_diff \n";
        }




        ($ltimes, $lgrade,$lname) = ($times, $grade,$name);
    }
}
}



> On 11 Sep 2016, at 00:52, Aaron Wells <chacewe...@gmail.com> wrote:
> 
> Hi there,
> 
> Me again. The sort function does NOT default to <=>. It defaults to string 
> comparison order. See the Perl doc for sort:
> "If SUBNAME or BLOCK is omitted, sorts in standard string comparison order. "
> 
> So assuming you want numbers sorting, 'sort { $a <=> $b } keys %{$nameref}' 
> would be the way to go.
> 
> 
> On Sat, Sep 10, 2016, 4:11 PM Jim Gibson <jsgib...@me.com 
> <mailto:jsgib...@me.com>> wrote:
> 
> > On Sep 9, 2016, at 8:54 AM, Nathalie Conte <nco...@ebi.ac.uk 
> > <mailto:nco...@ebi.ac.uk>> wrote:
> >
> > Hello,
> > I have a question about making a calculation within a loop
> >
> > I have a hash of hashes
> > ##############
> > #!/usr/bin/perl
> > use strict;
> > use warnings;
> >
> > use Data::Dumper qw(Dumper);
> >
> > my %grades;
> > $grades{"Foo "}{1}   = 97;
> > $grades{"Foo "}{2}    = 107;
> > $grades{"Peti "}{1}   = 88;
> > $grades{"Peti "}{3}  = 89;
> > $grades{"Peti "}{4}          = 99;
> >
> > print Dumper \%grades;
> > print "----------------\n";
> >
> > foreach my $name (  keys %grades) {
> >     foreach my $subject (sort {$a <=> $b} keys %{ $grades{$name} }) {
> >         print "$name, $subject: $grades{$name}{$subject}\n";
> >     }
> > }
> >
> > ##############
> > output is
> > $VAR1 = {
> >           'Peti ' => {
> >                        '4' => 99,
> >                        '1' => 88,
> >                        '3' => 89
> >                      },
> >           'Foo ' => {
> >                       '1' => 97,
> >                       '2' => 107
> >                     }
> >         };
> > ----------------
> > Peti , 1: 88
> > Peti , 3: 89
> > Peti , 4: 99
> > Foo , 1: 97
> > Foo , 2: 107
> > ###############
> > Now, what I would like to achieve:
> > I want to make a calculation, in each $name (Peti and Foo), calculate:
> > for Peti:
> > first line : no action
> > second line -(minus) 1st line:
> > print subject 3-1=2, 89-88=1
> > third line - 2nd line:
> > print subject 4-3=1, 99-89=10
> >
> > for foo:
> > first line : no action
> > second line -(minus) 1st line:
> > print subject 2-1=2, 107-97=10
> >
> 
> For each $name, declare two variables ($prev_subject and $prev_grade below) 
> to hold the subject and grade. These variables will be undefined during the 
> first pass through the inner loop:
> 
> for my $name ( keys %grades ) {
>   my $nameref = $grades{$name};  # do one hash lookup
>   my( $prev_subject, $prev_grade );
>   for my $subject ( sort keys %{$nameref} ) { # {$a<=>$b} is the default for 
> sort
>     my $grade = $nameref->{$subject};
>     if( defined $prev_subject ) {
>       my $subject_delta = $subject = $prev_subject;
>       my $grade_delta = $grade - $prev_grade;
>       print "$name:  $subject_delta:  $grade_delta\n";
>     }
>     $prev_subject = $subject;
>     $prev_grade = $grade;
>   }
> }
> 
> 
> 
> --
> To unsubscribe, e-mail: beginners-unsubscr...@perl.org 
> <mailto:beginners-unsubscr...@perl.org>
> For additional commands, e-mail: beginners-h...@perl.org 
> <mailto:beginners-h...@perl.org>
> http://learn.perl.org/ <http://learn.perl.org/>
> 
> 

Reply via email to