In list context, this sorts the LIST and returns the sorted list value. In scalar context, the behaviour ofsort
is undefined.
If SUBNAME or BLOCK is omitted,sort
s in standard string comparison order. If SUBNAME is specified, it gives the name of a subroutine that returns a numeric value less than, equal to, or greater than0
, depending on how the elements of the list are to be ordered. (The<=>
andcmp
operators are extremely useful in such routines.) SUBNAME may be a scalar variable name (unsubscripted), in which case the value provides the name of (or a reference to) the actual subroutine to use. In place of a SUBNAME, you can provide a BLOCK as an anonymous, in-line sort subroutine.
If the subroutine's prototype is($$)
, the elements to be compared are passed by reference in@_
, as for a normal subroutine. This is slower than unprototyped subroutines, where the elements to be compared are passed into the subroutine as the package global variables$a
and$b
(see example below).
If the subroutine is an XSUB, the elements to be compared are pushed on to the stack, the way arguments are usually passed to XSUBs.$a
and$b
are not set.
If two or more elements of LIST compare the same (i.e. the comparison operation returns 0 for them), they retain the relative order they had in LIST. In other words, sorting is stable (and has been since v5.8.0).
The values to be compared are always passed by reference and should not be modified.
You also cannot exit out of the sort block or subroutine using any of the loop control operators described inperlsyn or withgoto
.
Whenuse locale
(but notuse locale ':not_characters'
) is in effect,sort LIST
sorts LIST according to the current collation locale. Seeperllocale.
sort
returns aliases into the original list, much as a for loop's index variable aliases the list elements. That is, modifying an element of a list returned bysort
(for example, in aforeach
,map
orgrep
) actually modifies the element in the original list. This is usually something to be avoided when writing clear code.
Examples:
# sort lexicallymy @articles = sort @files;# same thing, but with explicit sort routinemy @articles = sort {$a cmp $b} @files;# now case-insensitivelymy @articles = sort {fc($a) cmp fc($b)} @files;# same thing in reversed ordermy @articles = sort {$b cmp $a} @files;# sort numerically ascendingmy @articles = sort {$a <=> $b} @files;# sort numerically descendingmy @articles = sort {$b <=> $a} @files;# this sorts the %age hash by value instead of key# using an in-line functionmy @eldest = sort { $age{$b} <=> $age{$a} } keys %age;# sort using explicit subroutine namesub byage { $age{$a} <=> $age{$b}; # presuming numeric}my @sortedclass = sort byage @class;sub backwards { $b cmp $a }my @harry = qw(dog cat x Cain Abel);my @george = qw(gone chased yz Punished Axed);print sort @harry; # prints AbelCaincatdogxprint sort backwards @harry; # prints xdogcatCainAbelprint 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 otherwisemy @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 speedmy (@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 tempsmy @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 herepackage main;my @new = sort Other::backwards @old;## using a prototype with function signatureuse feature 'signatures';sub function_with_signature :prototype($$) ($one, $two) { return $one <=> $two}my @new = sort function_with_signature @old;
Warning: syntactical care is required when sorting the list returned from a function. If you want to sort the list returned by the function callfind_records(@key)
, you can use:
my @contact = sort { $a cmp $b } find_records @key;my @contact = sort +find_records(@key);my @contact = sort &find_records(@key);my @contact = sort(find_records(@key));
If instead you want to sort the array@key
with the comparison routinefind_records()
then you can use:
my @contact = sort { find_records() } @key;my @contact = sort find_records(@key);my @contact = sort(find_records @key);my @contact = sort(find_records (@key));
$a
and$b
are set as package globals in the package the sort() is called from. That means$main::a
and$main::b
(or$::a
and$::b
) in themain
package,$FooPack::a
and$FooPack::b
in theFooPack
package, etc. If the sort block is in scope of amy
orstate
declaration of$a
and/or$b
, youmust spell out the full name of the variables in the sort block :
package main;my $a = "C"; # DANGER, Will Robinson, DANGER !!!print sort { $a cmp $b } qw(A C E G B D F H); # WRONGsub badlexi { $a cmp $b }print sort badlexi qw(A C E G B D F H); # WRONG# the above prints BACFEDGH or some other incorrect orderingprint sort { $::a cmp $::b } qw(A C E G B D F H); # OKprint sort { our $a cmp our $b } qw(A C E G B D F H); # also OKprint sort { our ($a, $b); $a cmp $b } qw(A C E G B D F H); # also OKsub lexi { our $a cmp our $b }print sort lexi qw(A C E G B D F H); # also OK# the above print ABCDEFGH
With proper care you may mix package and my (or state)$a
and/or$b
:
my $a = { tiny => -2, small => -1, normal => 0, big => 1, huge => 2};say sort { $a->{our $a} <=> $a->{our $b} } qw{ huge normal tiny small big};# prints tinysmallnormalbighuge
$a
and$b
are implicitly local to the sort() execution and regain their former values upon completing the sort.
Sort subroutines written using$a
and$b
are bound to their calling package. It is possible, but of limited interest, to define them in a different package, since the subroutine must still refer to the calling package's$a
and$b
:
package Foo;sub lexi { $Bar::a cmp $Bar::b }package Bar;... sort Foo::lexi ...
Use the prototyped versions (see above) for a more generic alternative.
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 results are not well-defined.
Because<=>
returnsundef
when either operand isNaN
(not-a-number), be careful when sorting with a comparison function like$a <=> $b
any lists that might contain aNaN
. The following example takes advantage thatNaN != NaN
to eliminate anyNaN
s from the input list.
my @result = sort { $a <=> $b } grep { $_ == $_ } @input;
In the current version of Perl, thesort
function is implemented via the mergesort algorithm.
Perldoc Browser is maintained by Dan Book (DBOOK). Please contact him via theGitHub issue tracker oremail regarding any issues with the site itself, search, or rendering of documentation.
The Perl documentation is maintained by the Perl 5 Porters in the development of Perl. Please contact them via thePerl issue tracker, themailing list, orIRC to report any issues with the contents or format of the documentation.