How can I sort a Perl hash on values and order the keys correspondingly (in two arrays maybe)?

106.8k views Asked by At

In Perl, I want to sort the keys of a hash by value, numerically:

{
  five => 5
  ten => 10
  one => 1
  four => 4
}

producing two arrays:

(1,4,5,10) and (one, four, five, ten)

And then I want to normalize the values array such that the numbers are sequential:

(1,2,3,4)

How do I do this?

3

There are 3 answers

2
ikegami On BEST ANSWER

First sort the keys by the associated value. Then get the values (e.g. by using a hash slice).

my @keys = sort { $h{$a} <=> $h{$b} } keys(%h);
my @vals = @h{@keys};

Or if you have a hash reference.

my @keys = sort { $h->{$a} <=> $h->{$b} } keys(%$h);
my @vals = @{$h}{@keys};
2
Axeman On
my ( @nums, @words );
do { push @nums,  shift @$_; 
     push @words, shift @$_; 
   }
    foreach sort { $a->[0] <=> $b->[0] } 
            map  { [ $h->{ $_ }, $_ ] } keys %$h
   ;
0
Clarius On

Sometimes it's best to show rather than tell...

%results = (Paul=>87, Ringo=>93, John=>91, George=>97);

#display the results in ascending key (alphabetical) order
print "key ascending...\n";
foreach $key ( sort { $a cmp $b } keys %results ){
    print "$key=>$results{$key}\n";
}

print "\n";

# display the results in descending key (alphabetical) order
print "key descending...\n";
foreach $key ( sort { $b cmp $a } keys %results ){
    print "$key=>$results{$key}\n";
}

print "\n";

# display the results in descending value (numerical) order
print "value ascending...\n";
foreach $key ( sort { $results{$a} <=> $results{$b} } keys %results ){
    print "$key=>$results{$key}\n";
}

print "\n";

# display the results in ascending value (numerical) order
print "value descending...\n";
foreach $key ( sort { $results{$b} <=> $results{$a} } keys %results ){
    print "$key=>$results{$key}\n";
}