Perl's built-in sort operator sorts text strings in their natural text order, by default. [1]
This is fine if you want to sort text strings: my @sorted = sort qw(Gilligan Skipper Professor Ginger Mary_Ann); but gets pretty messy when you want to sort numbers : my @wrongly_sorted = sort 1, 2, 4, 8, 16, 32; The resulting list is 1 , 16 , 2 , 32 , 4 , 8 . Why didn't sort order these properly? It treats each item as a string and sorts them in string order. Any string that begins with 3 sorts before any string that begins with 4 . You can fix this by overriding how Perl compares pairs of items in the list. By default, as Perl orders the items, a string comparison is used. A new comparison is specified using a sort block , placed between the sort keyword and the list of things to sort. [2]
Within the sort block, $a and $b stand in for two of the items to be sorted. The last evaluated expression must return a -1 , , or +1 value. [3] If the value is -1 , the value currently in $a must appear before the value in $b in the final sorted list. If the value is +1 , then the value in $a must appear after the value in $b in the final sorted list. If the value is 0, you don't know or can't tell, so the results are unpredictable. [4]
For example, to sort those numbers in their proper order, you can use a sort block comparing $a and $b , like so: my @numerically_sorted = sort { if ($a < $b) { -1 } elsif ($a > $b) { +1 } else { 0 } } 1, 2, 4, 8, 16, 32; Now you have a proper numeric comparison, so you have a proper numeric sort. Of course, this is far too much typing, so you can use the spaceship operator instead: my @numerically_sorted = sort { $a <=> $b } 1, 2, 4, 8, 16, 32; The spaceship operator returns -1 , , and + 1 , according to the rules discussed. A descending sort is as simple as reversing the position of $a and $b : my @numerically_descending = sort { $b <=> $a } 1, 2, 4, 8, 16, 32; In every place the previous sort expression returned -1 , this expression returns +1 , and vice versa. Thus, the sort is in the opposite order. It's also easy to remember because if $a is to the left of $b , you get out the lower items first, just like a and b would be in the resulting list. Likewise, a string sort can be indicated with cmp , although this is used less often because it is the default comparison. The cmp operator is handier when you have a more complex comparison, as you'll see shortly. |