kk1173 has asked for the wisdom of the Perl Monks concerning the following question:

I'm very new to perl. I have a file contains info like:

state:city:temp a:ad:70\n a:ac:56\n b:bc:56\n b:ad:90\n

...etc
I need to to calculate average temp of each state in another file. I'm using hash and not able to do it.

Replies are listed 'Best First'.
Re: Average calculation
by davido (Cardinal) on Oct 24, 2005 at 06:50 UTC

    What does your existing code look like? It could be that your implementation, using a hash (which seems entirely reasonable) is almost on the mark. Wouldn't it be of more value to you for us to help figure out what you're doing wrong, rather than having us provide you a cut-and-paste solution?

    Here's how I would do it: Create a hash. Then iterate over each line of the file. chomp each line (to get rid of the \n). split on the ':' character. Retain the first element (state) and the third element (temperature). push each temperature into an anonymous array held as the value of the hash element indexed by the state: push @{$states{$state}}, $temp;. Then open your output file. Iterate over each state in the hash. Calculate the average by summing all elements for a given state, and then dividing by the number of elements. Save to your output file the state name and the average temperature. close your output file. Be sure to check return values on filesystem calls such as open and close.


    Dave

Re: Average calculation
by blazar (Canon) on Oct 24, 2005 at 06:50 UTC

    "I'm using hash" is not illustrative enough of the code you've tried so far. Is this your homework? Do you want us to do it for you?

    Hints: first, learn about split. Then, suppose you somehow you've managed to obtain a %temp hash, which happens to be a "HoA"; you probably will do something like:

    for (keys %temp) { my $tot; $tot += $_ for @{ $temp{$_} }; print "Average for state '$_': ", $tot/@{ $temp{$_} }, "\n"; }

    but possibly with additional checks and taylored to your needs. Suggested readings: perlref and the other docs mentioned there under the heading "SEE ALSO".

Re: Average calculation
by jbrugger (Parson) on Oct 24, 2005 at 07:46 UTC
    Try to start at cpan, most of the work is already done for you.
    In your case, look at Statistics::Lite
    Next, try the tutorial-section of this site to get you started in perl.

    "We all agree on the necessity of compromise. We just can't agree on when it's necessary to compromise." - Larry Wall.
Re: Average calculation
by Perl Mouse (Chaplain) on Oct 24, 2005 at 11:31 UTC
    Untested:
    perl -F: -wane '$t{$F[0]}+=$F[2]; $c{$F[0]}++; END{printf "%s: %f\n", $_, $t{$_}/$c{$_} for keys %c}' file
    Perl --((8:>*
      The solution looks accurate, although, especially being terse, some added explanation for this newbie OP, or perhaps where to look in the docs, seems warranted.

      -M

      Free your mind

        Terse, cryptic, partially golfed answers are typically acceptable if the question smells like homework. Consider such to be defense mechanisms of the monestary; good answers to homework questions will attract more homework questions. I, and many others, believe many homework questions would decrease the value of this community.

        -Scott

        some added explanation for this newbie OP, or perhaps where to look in the docs, seems warranted.
        If you think that it is warranted, what's keeping you from posting it?
        Perl --((8:>*
Re: Average calculation
by Moron (Curate) on Oct 24, 2005 at 13:15 UTC
    Your data looks like it warrants a hash of hash rather than one-level hash structure; in other words it suggests something like:
    my %HoH = (); # 'my' declares at file scope in this case LoadFile(\%HoH); # passing by reference is more portable # if you later make a module Stats(\%HoH); sub LoadFile{ my $href = shift; # get the actual parameter open my $fileHandle, "<filepath" or die $!; while( <$fileHandle> { my ($st,$to,$te) = split( /\:/ ); $href -> { $st }{ $to } = $te; # load file data into the HoH } close $fileHandle; } sub Stats { my $href = shift; for my $st ( sort keys %$href ) { # in state order my $toref = $href -> { $st }; # ref. to town subhash my ( $count, $sum ) = (0,0); for my $to ( keys %$toref ) { # sum through towns # (any order will do) $count++; $sum += ( $toref -> { $to } ); # accumulate state aggregates } print "$st: " . $sum/$count . "\n"; # average for state = sum/count } }

    -M

    Free your mind