in reply to Re: calculate average from range of hash values (optimize)
in thread calculate average from range of hash values (optimize)

Nor do you need to make a copy of the hash.
use List::Util qw(sum); sub average { my ($data, $first, $last) = @_; my @goodkeys = grep exists $data->{$_}, $first .. $last; sum( @{$data}{@goodkeys} ) / @goodkeys; }
Finally, that we're doing math on the values without checking their definedness suggests that valid values are never undef, in which case you can skip the double lookup.
use List::Util qw(sum); sub average { my ($data, $first, $last) = @_; my @values = grep defined, @{$data}{$first .. $last}; sum(@values) / @values; }
That should be about as fast as you can get in Perl.

Makeshifts last the longest.

Replies are listed 'Best First'.
Re: Re^2: calculate average from range of hash values (optimize)
by demerphq (Chancellor) on Jul 27, 2003 at 13:59 UTC

    For the record your second solution corrupts the hash with keys whose value is undef. While the OP didnt explicitly say this was bad, I believe it was implicit in the comment that the keys could be very large or very small. Thus a search could inadverdantly create millions of keys and overflow available RAM.


    ---
    demerphq

    <Elian> And I do take a kind of perverse pleasure in having an OO assembly language...
      For the record your second solution corrupts the hash with keys whose value is undef.
      Eh? Extraordinarily strange. So a slice lookup autovivifies elements, while a single-element lookup doesn't. Feels like a bug, if you ask me.. certainly counterintuitive. Easy enough to fix, though.
      use List::Util qw(sum); sub average { my ($data, $first, $last) = @_; my @values = map { local $_ = $data->{$_}; defined() ? $_ : () } $ +first .. $last; sum(@values) / @values; }

      Makeshifts last the longest.