Sort hash by values

Viewed 67

This is not how I populated my hash. Just for easier reading, here are its contents, keys are on a fixed length string:

my %country_hash = (
  "001 Sample Name   New Zealand" => "NEW ZEALAND",
  "002 Samp2 Nam2    Zimbabwe   " => "ZIMBABWE",
  "003 SSS NNN       Australia  " => "AUSTRALIA",
  "004 John Sample   Philippines" => "PHILIPPINES,
);

I want to get the sorted keys based on values. So my expectation:

"003 SSS NNN       Australia  "
"001 Sample Name   New Zealand"
"004 John Sample   Philippines"
"002 Samp2 Nam2    Zimbabwe   "

What I did:

foreach my $line( sort {$country_hash{$a} <=> $country_hash{$b} or $a cmp $b} keys %country_hash ){
  print "$line\n";
}

also; (I doubted this will sort but anyway)

my @sorted = sort { $country_hash{$a} <=> $country_hash{$b} } keys %country_hash;
foreach my $line(@sorted){
  print "$line\n";
}

Neither of them sorted correctly. I hope someone could help.

1 Answers

If you had used warnings, you would have been told that <=> is the wrong operator; it is used for numeric comparison. Use cmp for string comparison instead. Refer to sort.

use warnings;
use strict;

my %country_hash = (
  "001 Sample Name   New Zealand" => "NEW ZEALAND",
  "002 Samp2 Nam2    Zimbabwe   " => "ZIMBABWE",
  "003 SSS NNN       Australia  " => "AUSTRALIA",
  "004 John Sample   Philippines" => "PHILIPPINES",
);

my @sorted = sort { $country_hash{$a} cmp $country_hash{$b} } keys %country_hash;
foreach my $line(@sorted){
    print "$line\n";
}

This prints:

003 SSS NNN       Australia  
001 Sample Name   New Zealand
004 John Sample   Philippines
002 Samp2 Nam2    Zimbabwe   

This also works (without the extra array):

foreach my $line (sort {$country_hash{$a} cmp $country_hash{$b}} keys %country_hash) {
    print "$line\n";
}
Related