Re: calculate within a loop

2016-09-21 Thread Chris Charley


""Chris Charley""  wrote in message 
news:20160912202839.22177.qm...@lists-nntp.develooper.com...


"Nathalie Conte"  wrote in message 
news:9d0654e0-8ec0-4051-87ca-541f90931...@ebi.ac.uk...

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,


#!/usr/bin/perl
use strict;
use warnings;
use List::Util 'sum';
use List::MoreUtils 'uniq';

my %hall = (
 '100 ' => {
 'y' => {
  '1' => 88,
  '3' => 89,
  '5'

Re: calculate within a loop

2016-09-14 Thread Chris Charley

""Chris Charley""  wrote in message 
news:20160912202839.22177.qm...@lists-nntp.develooper.com...

"Nathalie Conte"  wrote in message 
news:9d0654e0-8ec0-4051-87ca-541f90931...@ebi.ac.uk...
Dear all, 

[snip]

many thanks again for any tips/help,
Nathalie


[Chris wrote]

[snip]

for my $name (sort keys %hall) {
my $href = $hall{$name};
my @keys = uniq sort {$a <=> $b} map keys %$_, values %$href;

for my $i (0 .. $#keys) {
for my $j ($i+1 .. $#keys) {
my $sum = sum( map $_->{$keys[$j]}, values %$href) - 
   sum( map $_->{$keys[$i]}, values %$href);
printf "%s $keys[$j] minus $keys[$i] %s\n", $name, $sum;
}
}
}

Update: That print line is better written:
print "$name $keys[$j] minus $keys[$i] $sum\n";

And, to be a bit safer, the 2 calculated sums should be:
sum( map $_->{$keys[$j]} || 0, values %$href) 
sum( map $_->{$keys[$i]} || 0, values %$href);

where $_->{ $keys[$j] } and $_->{ $keys[$i] } default to ‘0’ if not contained 
in the hash (which doesn’t happen in the sample data provided anyhow).

Re: calculate within a loop

2016-09-12 Thread Uri Guttman

On 09/12/2016 06:48 PM, Aaron Wells wrote:

@Jim,

That eval bit i think Nathalie got from me. I need to review my core 
Perl. I think i’m in the habit of assuming Perl warns against any 
usage of undefined values, even in boolean context. Not so. I’ve 
proven to myself that this is not the case:





BLOCK eval doesn't trap warnings - it only traps die calls or fatal things.

as for no warnings on undef, it makes sense to allow undef as a boolean. 
there are other cases too where undef is not warned. using ++ on an 
undef is quiet (but not +=) as counting with ++ is too common and 
forcing the scalar to 0 first would be annoying.


uri



Re: calculate within a loop

2016-09-12 Thread Aaron Wells
@Jim,

That eval bit i think Nathalie got from me. I need to review my core Perl. I 
think i’m in the habit of assuming Perl warns against any usage of undefined 
values, even in boolean context. Not so. I’ve proven to myself that this is not 
the case:

$ perl -E’
>my ($foo, $bar); # these aren’t defined
>if ($foo and $bar) {
>  say “doing something”;
>} else {
>  say “doing nothing”;
>}’
**output**
$ doing nothing

Good catch. Thanks Jim :)
> On Sep 12, 2016, at 1:22 PM, Chris Charley  wrote:
> 
>  
> "Nathalie Conte" mailto:nco...@ebi.ac.uk>> wrote in 
> message news:9d0654e0-8ec0-4051-87ca-541f90931...@ebi.ac.uk 
> ...
> 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

Re: calculate within a loop

2016-09-12 Thread Chris Charley

"Nathalie Conte"  wrote in message 
news:9d0654e0-8ec0-4051-87ca-541f90931...@ebi.ac.uk...
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,

I see Jim Gibson has solved this but I thought I’d add another solution.

Although it is a little more complex, it is shorter than Jim’s. It makes use of 
2 modules: List::Util=(sum) and List::MoreUtils=(uniq).

#!/usr/bin/perl
use strict;
use warnings;
use List::Util 'sum';
use List::MoreUtils 'uniq';

my %hall = (
   

Re: calculate within a loop

2016-09-12 Thread Jim Gibson

> On Sep 12, 2016, at 6:24 AM, Nathalie Conte  wrote:
> 
> 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.
> ##
> 
> 
> 
> 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 .

You call the second level keys “levels” here, but in your code the variable you 
use to hold these key values is $subject. What you call “times” here are held 
in a variable called $values. That is confusing. It is better if your variable 
names describe what values they hold, e.g. $level, $time.

> 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 

I think that should be 23, because (117-97) is 20.

> 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

So it looks like you have a three-level hash of values (grades?) indexed by 
name (‘100’, ‘101’), level (‘x’, ‘y’, ‘z’), and time (1, 3, 5). For each name 
you want to iterate over pairs of times and perform calculations done by 
grouping the grades according to levels.

The first thing to notice is that you need to reorganize your hash so you can 
iterate over names and times.

> 
> ###
> 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!

%hall has three levels of hashes. So any value of %hall with only two indices 
will be a reference to a hash. if you want the scalar grade values, you must 
supply three indices.

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

Why the eval? You can evaluate logical expressions without doing the eval.

> 
> 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);
> }
> }
> }

Try this:

#!/usr/bin/perl
use strict;
use warnings;

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{"

Re: calculate within a loop

2016-09-12 Thread Nathalie Conte
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 su

Re: calculate within a loop

2016-09-10 Thread Aaron Wells
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  wrote:

>
> > On Sep 9, 2016, at 8:54 AM, Nathalie Conte  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
> For additional commands, e-mail: beginners-h...@perl.org
> http://learn.perl.org/
>
>
>


Re: calculate within a loop

2016-09-10 Thread Jim Gibson

> On Sep 9, 2016, at 8:54 AM, Nathalie Conte  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
For additional commands, e-mail: beginners-h...@perl.org
http://learn.perl.org/




Re: calculate within a loop

2016-09-09 Thread Gil Magno
Hi, Nathalie

You could try the attached code.

Best

gil

On 09/09/16 12:54, Nathalie Conte 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
> 
> 
> Many thanks for any advice
> Best
> Nathalie
> 
> 


q.pl
Description: Perl program


signature.asc
Description: OpenPGP digital signature