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

More golf than a q, I want to extract the $num lowest values from a hash, in a shorter way than the one i have below, the values will be numeric, the keys may not:
my %hash = ('1' => 12, '2' => 34, '3' => 56, '4' => 2); @values = reverse ((sort {$a <=> $b} values %hash)[0..--$num]);

Shorter offerings?

Replies are listed 'Best First'.
RE: extracting values from sort
by Jonathan (Curate) on Oct 04, 2000 at 14:26 UTC
    You don't need the reverse function, swap $a and $b around


    "We are all prompted by the same motives, all deceived by the same fallacies, all animated by hope, obstructed by danger, entangled by desire, and seduced by pleasure." - Samuel Johnson
      The reverse isn't reversing the sort, it's reversing the order of the elements of the list returned by the sliced sort.

      Check the parenthesis.

      ??
      swapping $a and $b and dropping reverse gives me 34, 56 ?
        Are you sure? On my box this is the same...
        #!/usr/local/bin/perl $num=5; my %hash = ('1' => 12, '2' => 34, '3' => 56, '4' => 2); @values = reverse ((sort {$a <=> $b} values %hash)[0..--$num]); print @values, "\n"; $num=5; @values = (sort {$b <=> $a} values %hash)[0..--$num]; print @values, "\n"; -----> /home/jonathan> z 5634122 5634122
        "We are all prompted by the same motives, all deceived by the same fallacies, all animated by hope, obstructed by danger, entangled by desire, and seduced by pleasure." - Samuel Johnson
Re: extracting values from sort
by kilinrax (Deacon) on Oct 04, 2000 at 14:22 UTC
    Update: I just benchmarked my original suggestion ('Lowest'), and it performs significanly worse than using sort; it's only faster with $num less than 3, and a $hash_size of several thousand :-(
    #!/usr/bin/perl -w require 5; use strict; use Benchmark; use vars qw( $hash_size %random_hash $num ); $num = 2; $hash_size = 1000; # Generate random hash my $r; for ($r=1; $r<=$hash_size; $r++) { $random_hash{"$r"} = int(rand(1000)); } sub Lowest(\%) { my $hashref = shift; my %hash = %{$hashref}; my $position; my $current; my @lowest; for ($position=0; $position<$num; $position++) { my $min; my $elem; foreach $elem (keys %hash) { if (!defined($min) || $hash{$elem} < $min) { $min = $hash{$elem}; $current = $elem; } } $lowest[$position] = $min; delete $hash{$current}; last if !(%hash); } return @lowest; } sub Sort(\%) { my $hashref = shift; my %hash = %{$hashref}; my @lowest = (sort {$b <=> $a} values %hash)[0..--$num]; return @lowest; } timethese ( -20, { 'Method 1' => 'Lowest(%random_hash)', 'Method 2' => 'Sort(%random_hash)' }); exit;

    abowley@lave:~$ ./lowest.pl Benchmark: running Method 1, Method 2, each for at least 20 CPU second +s... Method 1: 25 wallclock secs (19.80 usr + 0.21 sys = 20.01 CPU) @ 42 +.53/s (n=851) Method 2: 25 wallclock secs (20.33 usr + 0.22 sys = 20.55 CPU) @ 43 +.16/s (n=887)