perl getting 0 instead of output

Viewed 82

the file I am working with has the following information in the columns trying to get the name, average, min and max of each name

Name,   Category,    Assignment,  Score,   Possible,
Al,        test,        T1,         90,      100
Ben,       test,        T1,        80,      100
Al ,      lab,         L1,         76,      100
Ben,       lab,         L1,         67,      100

the first issue I had with the code was it kept saying there was an illegal division at line 25, I changed some stuff around and now I'm getting

Name Average Min Max0

as my output instead of anything actually being done math wise I'm not really sure where my issues are

#!/usr/bin/perl
my %total;
my %count;
my %min;
my %max;
while(<>){
    chomp;
    @fields = split(/,/, $_);
    if(@fields[0] !~ /Student/){
        $total{@fields[2]} += @fields[5];
        $count{@fields[5]}++;
    }
    if($min{@fields[2]} > @fields[5]){
        $min{@fields[2]} = @fields[5];
    } elsif($min{@fields}[2] == 0){
        $min{@fields[2]} = @fields[5];
    }
    if($max{@fields[2]} < @fields[5]){
        $max{@fields[2]} = @fields[5]
    }
}
print "Name\tAverage\tMin\tMax";
foreach $total(keys %count){
    print $total . "\t" . $total{$type}/$count{$type} . $min{$type} . "\t" . $min{$type} . "\t". $max{$type} . "\n";
}

the expected output

Name Average   Low High
Q1       83    76    90
L1       73.5  67    80
2 Answers

The major problems:

  • You never assign anything to $type. (It's not even declared).

  • %count only has one element because @fields[5] is always undefined because your data only has 5 fields.

  • $total isn't the count; it's (the stringification of) the value returned by @fields[5].

  • You don't emit a line feed after your header.

ALWAYS use use strict; use warnings;.

OP's mistakes already was described, next code demonstration how to utilize hash to name fields of data. This approach should make code easier to read and understand and will not require to count what number is for a particular field.

use strict;
use warnings;
use feature 'say';

my @fields = qw/Name Category Assignment Score Possible/;
my(%data,$result);

while(<DATA>) {
    next if /$fields[0]/;
    @data{@fields} = split(/[\s,]+/,$_);
    $result->{$data{Assignment}}{min} = $result->{$data{Assignment}}{min} // 100;
    $result->{$data{Assignment}}{max} = $result->{$data{Assignment}}{max} // 0;
    $result->{$data{Assignment}}{min} = $data{Score}
        if $data{Score} < $result->{$data{Assignment}}{min};
    $result->{$data{Assignment}}{max} = $data{Score}
        if $data{Score} > $result->{$data{Assignment}}{max};
    $result->{$data{Assignment}}{total} += $data{Score};
    $result->{$data{Assignment}}{count}++;
}

my @header = qw/Name Average Low High/;
say join("\t",@header);

for( sort keys %$result ) {
    say join("\t",
                (   
                    $_,
                    $result->{$_}{total}/$result->{$_}{count},
                    $result->{$_}{min},
                    $result->{$_}{max}
                )
            );
}

__DATA__
Name,   Category,    Assignment,  Score,   Possible,
Al,        test,        T1,         90,      100
Ben,       test,        T1,        80,      100
Al ,      lab,         L1,         76,      100
Ben,       lab,         L1,         67,      100

Or shorter version

use strict;
use warnings;
use feature 'say';

my $result;

while(<DATA>) {
    next if /^Name/;
    my($assig,$score) = (split(/[\s,]+/,$_))[2,3];
    $result->{$assig}{min} = $result->{$assig}{min} // 100;
    $result->{$assig}{max} = $result->{$assig}{max} // 0;
    $result->{$assig}{min} = $score
        if $score < $result->{$assig}{min};
    $result->{$assig}{max} = $score
        if $score > $result->{$assig}{max};
    $result->{$assig}{total} += $score;
    $result->{$assig}{count}++;
}

my @header = qw/Name Average Low High/;
say join("\t",@header);

for( sort keys %$result ) {
    say join("\t",
                (   
                    $_,
                    $result->{$_}{total}/$result->{$_}{count},
                    $result->{$_}{min},
                    $result->{$_}{max}
                )
            );
}

__DATA__
Name,   Category,    Assignment,  Score,   Possible,
Al,        test,        T1,         90,      100
Ben,       test,        T1,        80,      100
Al ,      lab,         L1,         76,      100
Ben,       lab,         L1,         67,      100

Output

Name    Average Low     High
L1      71.5    67      76
T1      85      80      90
Related