sort LISTIn list context, this sorts the LIST and returns the sorted list value.In scalar context, the behaviour of sort()
is undefined.
If SUBNAME or BLOCK is omitted, sort
s in standard string comparisonorder. If SUBNAME is specified, it gives the name of a subroutinethat returns an integer less than, equal to, or greater than 0
,depending on how the elements of the list are to be ordered. (The <=>
and cmp
operators are extremely useful in such routines.)SUBNAME may be a scalar variable name (unsubscripted), in which casethe value provides the name of (or a reference to) the actualsubroutine to use. In place of a SUBNAME, you can provide a BLOCK asan anonymous, in-line sort subroutine.
If the subroutine's prototype is ($$)
, the elements to be compared arepassed by reference in @_
, as for a normal subroutine. This is slowerthan unprototyped subroutines, where the elements to be compared are passedinto the subroutine as the package global variables $a and $b (see examplebelow). Note that in the latter case, it is usually highly counter-productiveto declare $a and $b as lexicals.
If the subroutine is an XSUB, the elements to be compared are pushed on tothe stack, the way arguments are usually passed to XSUBs. $a and $b arenot set.
The values to be compared are always passed by reference and should notbe modified.
You also cannot exit out of the sort block or subroutine using any of theloop control operators described in perlsyn or with goto
.
When use locale
(but not use locale 'not_characters'
) is ineffect, sort LIST
sorts LIST according to thecurrent collation locale. See perllocale.
sort() returns aliases into the original list, much as a for loop's indexvariable aliases the list elements. That is, modifying an element of alist returned by sort() (for example, in a foreach
, map
or grep
)actually modifies the element in the original list. This is usuallysomething to be avoided when writing clear code.
Perl 5.6 and earlier used a quicksort algorithm to implement sort.That algorithm was not stable, so could go quadratic. (A stable sortpreserves the input order of elements that compare equal. Althoughquicksort's run time is O(NlogN) when averaged over all arrays oflength N, the time can be O(N**2), quadratic behavior, for someinputs.) In 5.7, the quicksort implementation was replaced witha stable mergesort algorithm whose worst-case behavior is O(NlogN).But benchmarks indicated that for some inputs, on some platforms,the original quicksort was faster. 5.8 has a sort pragma forlimited control of the sort. Its rather blunt control of theunderlying algorithm may not persist into future Perls, but theability to characterize the input or output in implementationindependent ways quite probably will. See the sort pragma.
Examples:
- # sort lexically
- @articles = sort @files;
-
- # same thing, but with explicit sort routine
- @articles = sort {$a cmp $b} @files;
-
- # now case-insensitively
- @articles = sort {fc($a) cmp fc($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;
-
- # this sorts the %age hash by value instead of key
- # using an in-line function
- @eldest = sort { $age{$b} <=> $age{$a} } keys %age;
-
- # sort using explicit subroutine name
- sub byage {
- $age{$a} <=> $age{$b}; # presuming numeric
- }
- @sortedclass = sort byage @class;
-
- sub backwards { $b cmp $a }
- @harry = qw(dog cat x Cain Abel);
- @george = qw(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
- my @new = sort {
- ($b =~ /=(\d+)/)[0] <=> ($a =~ /=(\d+)/)[0]
- ||
- fc($a) cmp fc($b)
- } @old;
- # same thing, but much more efficiently;
- # we'll build auxiliary indices instead
- # for speed
- my @nums = @caps = ();
- for (@old) {
- push @nums, ( /=(\d+)/ ? $1 : undef );
- push @caps, fc($_);
- }
- my @new = @old[ sort {
- $nums[$b] <=> $nums[$a]
- ||
- $caps[$a] cmp $caps[$b]
- } 0..$#old
- ];
- # same thing, but without any temps
- @new = map { $_->[0] }
- sort { $b->[1] <=> $a->[1]
- ||
- $a->[2] cmp $b->[2]
- } map { [$_, /=(\d+)/, fc($_)] } @old;
- # using a prototype allows you to use any comparison subroutine
- # as a sort subroutine (including other package's subroutines)
- package other;
- sub backwards ($$) { $_[1] cmp $_[0]; } # $a and $b are not set here
-
- package main;
- @new = sort other::backwards @old;
-
- # guarantee stability, regardless of algorithm
- use sort 'stable';
- @new = sort { substr($a, 3, 5) cmp substr($b, 3, 5) } @old;
-
- # force use of mergesort (not portable outside Perl 5.8)
- use sort '_mergesort'; # note discouraging _
- @new = sort { substr($a, 3, 5) cmp substr($b, 3, 5) } @old;
Warning: syntactical care is required when sorting the list returned froma function. If you want to sort the list returned by the function callfind_records(@key)
, you can use:
- @contact = sort { $a cmp $b } find_records @key;
- @contact = sort +find_records(@key);
- @contact = sort &find_records(@key);
- @contact = sort(find_records(@key));
If instead you want to sort the array @key with the comparison routinefind_records()
then you can use:
- @contact = sort { find_records() } @key;
- @contact = sort find_records(@key);
- @contact = sort(find_records @key);
- @contact = sort(find_records (@key));
If you're using strict, you must not declare $aand $b as lexicals. They are package globals. That meansthat if you're in the main
package and type
- @articles = sort {$b <=> $a} @files;
then $a
and $b
are $main::a
and $main::b
(or $::a
and $::b
),but if you're in the FooPack
package, it's the same as typing
- @articles = sort {$FooPack::b <=> $FooPack::a} @files;
The comparison function is required to behave. If it returnsinconsistent results (sometimes saying $x[1]
is less than $x[2]
andsometimes saying the opposite, for example) the results are notwell-defined.
Because <=>
returns undef
when either operand is NaN
(not-a-number), be careful when sorting with acomparison function like $a <=> $b
any lists that might contain aNaN
. The following example takes advantage that NaN != NaN
toeliminate any NaN
s from the input list.
- @result = sort { $a <=> $b } grep { $_ == $_ } @input;