sort#
Sort a list, returning the sorted list.
sort takes a list and returns a new list with the elements rearranged
in order. With no comparator it uses standard string comparison. With
a BLOCK or a SUBNAME you supply the comparison rule as a small
function that is called for each pair of elements and must return a
negative, zero, or positive value the way cmp and <=> do.
Sorting is stable — elements that compare equal keep their original relative order. The algorithm is mergesort.
Synopsis#
sort LIST
sort BLOCK LIST
sort SUBNAME LIST
Three idiomatic forms:
my @out = sort @in; # default: string cmp, ascending
my @out = sort { $a <=> $b } @in; # numeric, ascending
my @out = sort by_name @in; # named comparator sub
What you get back#
A new sorted list. sort does not modify the input in place.
To replace an array with its sorted version you assign back:
@a = sort @a;
In list context the return is the sorted list. In scalar context the
return value is undefined — do not use scalar sort.
The returned list contains aliases into the original list, exactly
like a foreach index variable. Modifying an element of the result
inside a later foreach, map, or grep therefore modifies the
original element too. This is almost never what you want; treat the
result as read-only.
Global state: $a and $b#
Inside the comparator BLOCK or SUBNAME, the two elements being
compared are exposed as the package globals $a and $b. These are
not parameters and they are not lexicals — they are real package
variables that sort localises for you around the call.
$aand$blive in the package that calledsort. Inmain, that is$main::aand$main::b; inFoo,$Foo::aand$Foo::b.Never declare
my $aormy $banywhere the sort block can see. A lexical$aor$bshadows the package global; the block then compares two unrelated variables and the sort silently produces garbage. Underuse warningsyou get no warning for this.If you genuinely need
$a/$bas lexicals elsewhere, refer to the sort variables by full name inside the block:print sort { $::a cmp $::b } qw(A C E G B D F H); print sort { our $a cmp our $b } qw(A C E G B D F H);
A comparator defined with the prototype
($$)(or an equivalent signature attribute) receives the pair in@_instead of$aand$b. This is slower than the$a/$bconvention but decouples the sub from the caller’s package.
Both elements are passed by reference; mutating $a or $b in
the block mutates the original list. Don’t.
Examples#
Default string sort:
my @sorted = sort qw(banana apple cherry);
# ('apple', 'banana', 'cherry')
Numeric ascending — the default sort @nums would sort "10" before
"2" because comparison is by string:
my @nums = sort { $a <=> $b } (10, 2, 33, 4);
# (2, 4, 10, 33)
Numeric descending — swap $a and $b:
my @nums = sort { $b <=> $a } (10, 2, 33, 4);
# (33, 10, 4, 2)
Multi-key sort with a tiebreaker. || runs the second comparator
only when the first returns 0:
my @people = sort {
$a->{last} cmp $b->{last}
|| $a->{first} cmp $b->{first}
} @records;
Sort a hash’s keys by the associated value:
my %age = (alice => 30, bob => 25, carol => 40);
my @by_age = sort { $age{$a} <=> $age{$b} } keys %age;
# ('bob', 'alice', 'carol')
Schwartzian Transform — when the sort key is expensive to compute,
precompute it once per element, sort the [key, value] pairs, then
strip the keys. Three stages, read bottom-up:
my @sorted =
map { $_->[1] } # 3. strip key
sort { $a->[0] <=> $b->[0] } # 2. sort by key
map { [ expensive_key($_), $_ ] } # 1. attach key
@input;
Named comparator sub. The sub reads $a and $b from the caller’s
package, so it must be in (or referenced from) that package:
sub by_name { $a->{name} cmp $b->{name} }
my @sorted = sort by_name @people;
Prototyped comparator — arguments arrive in @_, so it works from
any package:
sub numeric ($$) { $_[0] <=> $_[1] }
my @sorted = sort numeric @nums;
Edge cases#
$aand$bare package globals, not lexicals. A straymy $ain scope silently breaks every sort in that scope. If you must, useour $aor$::ainside the block.<=>is numeric,cmpis string. Using the wrong one is the most common sort bug.sort { $a cmp $b } (10, 2, 33)yields(10, 2, 33)— lexicographic,"10"before"2". Use<=>for numbers.Empty list returns an empty list.
sort ()is(). No error.Single element is returned unchanged. No comparisons happen.
Comparator must be consistent. If it sometimes says
$x < $yand sometimes says the opposite for the same pair, the result is undefined. The comparator must return a total ordering: negative, zero, or positive, stably, for every call.NaNpoisons<=>.$a <=> $breturnsundefif either operand isNaN, whichsortthen treats as0— equal — giving an arbitrary placement. Filter first:my @clean = sort { $a <=> $b } grep { $_ == $_ } @input;
Stable sort. Equal elements keep their input order. Rely on this for multi-pass sorts (sort by secondary key first, then by primary key).
use sort 'stable'is the default and a no-op;use sort '_mergesort'/'_qsort'pragmas are historical and have no effect on current Perl.sortis not in-place.sort @adoes not touch@a. Use@a = sort @ato replace it. Assigning tosort’s result list aliases back into the original, so(sort @a)[0] = ...modifies@a’s smallest element.No loop control out of the block.
last,next,redo,return, andgoto LABELdo not work inside a sort comparator — the block is not a loop body.Parser trap: sorting a function’s return value.
sorttakes aLIST, so a following bareword can be mistaken for aSUBNAME. To sort the result offind_records(@key):my @out = sort { $a cmp $b } find_records @key; # OK my @out = sort +find_records(@key); # OK my @out = sort(find_records(@key)); # OK
To use
find_recordsas the comparator over@keyinstead:my @out = sort find_records @key; # comparator form my @out = sort { find_records() } @key; # block form
Locale-aware sorting. Under
use locale(without':not_characters') the default string comparison follows the current collation locale instead of codepoint order.XSUB comparators. If the comparator is an XSUB, the pair is passed on the argument stack the way XS functions normally receive arguments;
$aand$bare not set.
Differences from upstream#
Fully compatible with upstream Perl 5.42.
See also#
reverse— reverses a list; combine withsortfor descending sorts when the comparator is hard to invert by swapping$aand$bmap— the other half of the Schwartzian Transform; use to attach and strip sort keys around asortgrep— prefilter the list (e.g. removeNaNorundef) before handing it tosort$a— the first element in the comparison pair, aliased as a package global for the duration of the sort$b— the second element in the comparison pair, same lifetime and scoping rules as$a<=>— numeric three-way comparison; the usual operator inside a numeric sort blockcmp— string three-way comparison; the usual operator inside a string sort block