> On Sep 12, 2016, at 6:24 AM, Nathalie Conte <[email protected]> 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{"101 "}{'y'}{3} = 189;
$hall{"101 "}{'y'}{5} = 199;
$hall{"101 "}{'z'}{1} = 195;
$hall{"101 "}{'z'}{3} = 197;
$hall{"101 "}{'z'}{5} = 194;
# reorder hash from ( name, level, time ) to ( name, time, level )
my %rehash;
for my $name ( keys %hall) {
for my $level ( keys %{$hall{$name}} ) {
for my $time ( keys %{$hall{$name}{$level}} ) {
$rehash{$name}{$time}{$level} =
$hall{$name}{$level}{$time};
}
}
}
# iterate over names
for my $name ( sort keys %rehash ) {
print "\nName: $name\n";
# calculate sums over levels for each time
my $name_ref = $rehash{$name};
my @pg;
for my $time ( sort keys %{$name_ref} ) {
my $time_ref = $name_ref->{$time};
my $sum;
# sum over all levels
for my $level ( sort keys %{$time_ref} ) {
my $grade = $time_ref->{$level};
$sum += $grade;
}
# save results in array
push( @pg, [ $time, $sum ]);
# if more than one saved sum, calculate difference with all
previous sums
if( $#pg > 0 ) {
for my $i ( 0..$#pg-1 ) {
my( $t, $s ) = @{$pg[$i]};
my $val = $sum - $s;
print "Difference between time $time and time
$t: $val\n";
}
}
}
}
__END__
Which produces this:
Name: 100
Difference between time 3 and time 1: 23
Difference between time 5 and time 1: 20
Difference between time 5 and time 3: -3
Name: 101
Difference between time 3 and time 1: 923
Difference between time 5 and time 1: 920
Difference between time 5 and time 3: -3
--
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]
http://learn.perl.org/