Perl5 リファレンス



sort LIST


LIST をソートし、ソートされたリストの値を返します。SUBNAME または BLOCK が省略された場合には、標準文字列比較順で並べ替えられます。SUBNAME には、サブルーチンの名前を指定します。そのサブルーチンは、リストの並べ替え方によって整数を返すものでなければいけません。(<=> と cmp 演算子は、非常に便利です)
SUBNAME は、スカラー変数名でも大丈夫です。この場合、スカラー変数の値は、実際のサブルーチンの名前となります。SUBNAME の代わりに、匿名のインラインソートサブルーチンとして BLOCK を使うことともできます。

サブルーチンのプロトタイプが ($$) の場合、比較する要素は、リファレンスによって @_ にパスされます。

               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).  Note that in the latter case, it
               is usually counter-productive to declare $a and $b
               as lexicals.

               In either case, the subroutine may not be
               recursive.  The values to be compared are always
               passed by reference, so don't modify them.

               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.


                   # 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;

                   # 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

                   @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, but without any temps
                   @new = map { $_->[0] }
                          sort { $b->[1] <=> $a->[1]
                                 $a->[2] cmp $b->[2]
                          } map { [$_, /=(\d+)/, uc($_)] } @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;

               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 results are not