Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.

calculating array average in HoA

by benben (Novice)
on Apr 21, 2012 at 20:32 UTC ( #966408=perlquestion: print w/replies, xml ) Need Help??

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

Hi, I have a hash of arrays like this:

%HoA = ( A => [2.34, 4.12, 5.32], B => [1.42, 8.15], C => [8.42, 0.23, 0.45, 6.43], ###...and so on );

I want to calculate average of each array and display the result like:

A 3.93 B 4.79 ...etc.

I'm not sure how to do this though... that's what I've written so far: Any suggetions?

my $average; foreach my $key (keys %HoA) { foreach my $value (values %HoA) { my @Array = $value; $average = average (\@Array); } print $key, "\t", $average, "\n", } sub average { my ($array_ref) = @_; my $sum; my $count = scalar @$array_ref; foreach (@$array_ref) { $sum += $_; } my $av = $sum/$count; return $av; }

Replies are listed 'Best First'.
Re: calculating array average in HoA
by choroba (Cardinal) on Apr 21, 2012 at 20:38 UTC
    You are almost there. Just do not loop over values and keys:
    use warnings; use strict; my %HoA = ( A => [2.34, 4.12, 5.32], B => [1.42, 8.15], C => [8.42, 0.23, 0.45, 6.43], ); foreach my $key (keys %HoA) { print $key, "\t", average($HoA{$key}), "\n"; } sub average { my $array_ref = shift; my $sum; foreach (@$array_ref) { $sum += $_; } my $av = $sum / @$array_ref; return $av; }
Re: calculating array average in HoA
by aaron_baugher (Curate) on Apr 21, 2012 at 21:28 UTC

    Your main problem is here:

    foreach my $key (keys %HoA) { foreach my $value (values %HoA) { my @Array = $value;

    For each key in your hash, you're looping through all the values in your hash. You want to loop through the keys, and for each one, average the values in the particular array that it points to. Also, in the last line above, assigning a scalar to an array will simply make the scalar the first element of the array. Since your scalar is an array reference, you want to dereference it to get the array it points to. Which gives you these lines instead of the above:

    for my $key (keys %HoA){ # loop through the keys my $value = $HoA{$key}; # get the array ref for this key my @Array = @{$value}; # dereference it to get the array

    You can shorten that up and eliminate a step or two once you understand it, but that's the process broken down into small steps.

    One last thing: no need to instantiate $average outside your loop, since you only use it inside the loop. Better to instantiate it inside, in the narrowest possible context.

    Edited: Had a typo, $Array instead of @Array.

    Aaron B.
    My Woefully Neglected Blog, where I occasionally mention Perl.

Re: calculating array average in HoA
by jwkrahn (Monsignor) on Apr 22, 2012 at 03:15 UTC
    $ perl -e' use List::Util q/sum/; my %HoA = ( A => [ 2.34, 4.12, 5.32 ], B => [ 1.42, 8.15 ], C => [ 8.42, 0.23, 0.45, 6.43 ], ); for my $key ( keys %HoA ) { printf "%s\t%.2f\n", $key, sum( @{ $HoA{ $key } } ) / @{ $HoA{ $ke +y } }; } ' A 3.93 C 3.88 B 4.79
Re: calculating array average in HoA
by JavaFan (Canon) on Apr 21, 2012 at 20:52 UTC
    local $" = "+"; printf "%s %.2f\n", $_, (eval "@{$HoA{$_}}") / @{$HoA{$_}} for keys % +HoA;

      Just out of curiosity, how did the OP err in their question to justify such an obfuscated, likely unhelpful response?

        Why do you think the OP had to err to get JavaFans reply? Also why do you think it is obfuscated and unhelpful?

        I say the line local $" = "+"; pretty much explained the rest of the code, and to me at least it was faster to understand JavaFans code than the first answer even though my solution would have been closer to that first answer.

      JavaFan, you have my apology if your reply to the OP wasn't meant to be sarcastic. We've just seen a fair amount of that lately, even on posts where the SoPW lay out relatively decent questions.

      Normally I'd discuss such an issue if I have one with the author of a post, especially if the tone of the reply is ambiguous in my mind, like this one is now.

      I spoke before I thought in this case, and alcohol wasn't even involved ;)

Re: calculating array average in HoA
by Kenosis (Priest) on Apr 21, 2012 at 21:28 UTC

    Brilliant solution, JavaFan! A sort before keys would 'prettify' the output.

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://966408]
Approved by Happy-the-monk
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others taking refuge in the Monastery: (3)
As of 2023-12-01 19:57 GMT
Find Nodes?
    Voting Booth?
    What's your preferred 'use VERSION' for new CPAN modules in 2023?

    Results (5 votes). Check out past polls.