sort BLOCK LIST
sort LIST
<=>
and cmp
operators are extremely useful in such routines.)
SUBNAME may be a scalar variable name, in which case the value provides the name of the subroutine to use. In place of a
SUBNAME, you can provide a
BLOCK as an anonymous, in-line sort subroutine.
In the interests of efficiency the normal calling code for subroutines is
bypassed, with the following effects: the subroutine may not be a recursive
subroutine, and the two elements to be compared are passed into the
subroutine not via @_
but as the package global variables
$a
and $b
(see example below). They are passed by
reference, so don't modify $a
and $b. And don't try to declare
them as lexicals either.
You also cannot exit out of the sort block or subroutine using any of the
loop control operators described in the perlsyn manpage or with goto.
When use locale
is in effect, sort LIST
sorts
LIST according to the current collation locale. See the perllocale manpage.
Examples:
# sort lexically @articles = sort @files;
# same thing, but with explicit sort routine @articles = sort {$a cmp $b} @files;
# now case-insensitively @articles = sort { uc($a) cmp uc($b)} @files;
# same thing in reversed order @articles = sort {$b cmp $a} @files;
# sort numerically ascending @articles = sort {$a <=> $b} @files;
# sort numerically descending @articles = sort {$b <=> $a} @files;
# sort using explicit subroutine name sub byage { $age{$a} <=> $age{$b}; # presuming numeric } @sortedclass = sort byage @class;
# this sorts the %age hash by value instead of key # using an in-line function @eldest = sort { $age{$b} <=> $age{$a} } keys %age;
sub backwards { $b cmp $a; } @harry = ('dog','cat','x','Cain','Abel'); @george = ('gone','chased','yz','Punished','Axed'); print sort @harry; # prints AbelCaincatdogx print sort backwards @harry; # prints xdogcatCainAbel print sort @george, 'to', @harry; # prints AbelAxedCainPunishedcatchaseddoggonetoxyz
# inefficiently sort by descending numeric compare using # the first integer after the first = sign, or the # whole record case-insensitively otherwise
@new = sort { ($b =~ /=(\d+)/)[0] <=> ($a =~ /=(\d+)/)[0] || uc($a) cmp uc($b) } @old;
# same thing, but much more efficiently; # we'll build auxiliary indices instead # for speed @nums = @caps = (); for (@old) { push @nums, /=(\d+)/; push @caps, uc($_); }
@new = @old[ sort { $nums[$b] <=> $nums[$a] || $caps[$a] cmp $caps[$b] } 0..$#old ];
# same thing using a Schwartzian Transform (no temps) @new = map { $_->[0] } sort { $b->[1] <=> $a->[1] || $a->[2] cmp $b->[2] } map { [$_, /=(\d+)/, uc($_)] } @old;
If you're using strict, you MUST NOT declare $a
and $b
as lexicals. They are package
globals. That means if you're in the main
package, it's
@articles = sort {$main::b <=> $main::a} @files;
or just
@articles = sort {$::b <=> $::a} @files;
but if you're in the FooPack
package, it's
@articles = sort {$FooPack::b <=> $FooPack::a} @files;
The comparison function is required to behave. If it returns inconsistent
results (sometimes saying $x[1] is less than $x[2] and sometimes saying the
opposite, for example) the Perl interpreter will probably crash and dump
core. This is entirely due to and dependent upon your system's
qsort
library routine; this routine often avoids sanity checks
in the interest of speed.