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

I don't see the need to sort all the keys in %{$data}. You can use hash slices and List::Utils::sum() to good advantage.

use List::Utils 'sum'; sub average { my ($data, $first, $last) = @_; my %data = %$data; my @goodkeys = grep {exists $data{$_}} $first .. $last; sum( @data{ @goodkeys } ) / @goodkeys; }

After Compline,
Zaxo

Replies are listed 'Best First'.
Re^2: calculate average from range of hash values (optimize)
by Aristotle (Chancellor) on Jul 27, 2003 at 02:12 UTC
    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.

      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.