perl sort

sort

  • sort SUBNAME LIST

  • sort BLOCK LIST
  • sort LIST

    In 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, sorts in standard string comparison order. If SUBNAME is specified, it gives the name of a subroutine that 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 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). Note that in the latter case, it is usually highly counter-productive to declare $a and $b as lexicals.

    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 with goto.

    When use locale is in effect, sort LIST sorts LIST according to the current collation locale. See perllocale.

    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 by sort() (for example, in a foreach , map or grep) actually modifies the element in the original list. This is usually something 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 sort preserves the input order of elements that compare equal. Although quicksort's run time is O(NlogN) when averaged over all arrays of length N, the time can be O(N**2), quadratic behavior, for some inputs.) In 5.7, the quicksort implementation was replaced with a 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 for limited control of the sort. Its rather blunt control of the underlying algorithm may not persist into future Perls, but the ability to characterize the input or output in implementation independent ways quite probably will. See the sort pragma.

    Examples:

       
       
    1. # sort lexically
    2. @articles = sort @files;
    3. # same thing, but with explicit sort routine
    4. @articles = sort {$a cmp $b} @files;
    5. # now case-insensitively
    6. @articles = sort {uc($a) cmp uc($b)} @files;
    7. # same thing in reversed order
    8. @articles = sort {$b cmp $a} @files;
    9. # sort numerically ascending
    10. @articles = sort {$a <=> $b} @files;
    11. # sort numerically descending
    12. @articles = sort {$b <=> $a} @files;
    13. # this sorts the %age hash by value instead of key
    14. # using an in-line function
    15. @eldest = sort { $age{$b} <=> $age{$a} } keys %age;
    16. # sort using explicit subroutine name
    17. sub byage {
    18. $age{$a} <=> $age{$b}; # presuming numeric
    19. }
    20. @sortedclass = sort byage @class;
    21. sub backwards { $b cmp $a }
    22. @harry = qw(dog cat x Cain Abel);
    23. @george = qw(gone chased yz Punished Axed);
    24. print sort @harry;
    25. # prints AbelCaincatdogx
    26. print sort backwards @harry;
    27. # prints xdogcatCainAbel
    28. print sort @george, 'to', @harry;
    29. # prints AbelAxedCainPunishedcatchaseddoggonetoxyz
    30. # inefficiently sort by descending numeric compare using
    31. # the first integer after the first = sign, or the
    32. # whole record case-insensitively otherwise
    33. my @new = sort {
    34. ($b =~ /=(\d+)/)[0] <=> ($a =~ /=(\d+)/)[0]
    35. ||
    36. uc($a) cmp uc($b)
    37. } @old;
    38. # same thing, but much more efficiently;
    39. # we'll build auxiliary indices instead
    40. # for speed
    41. my @nums = @caps = ();
    42. for (@old) {
    43. push @nums, ( /=(\d+)/ ? $1 : undef );
    44. push @caps, uc($_);
    45. }
    46. my @new = @old[ sort {
    47. $nums[$b] <=> $nums[$a]
    48. ||
    49. $caps[$a] cmp $caps[$b]
    50. } 0..$#old
    51. ];
    52. # same thing, but without any temps
    53. @new = map { $_->[0] }
    54. sort { $b->[1] <=> $a->[1]
    55. ||
    56. $a->[2] cmp $b->[2]
    57. } map { [$_, /=(\d+)/, uc($_)] } @old;
    58. # using a prototype allows you to use any comparison subroutine
    59. # as a sort subroutine (including other package's subroutines)
    60. package other;
    61. sub backwards ($$) { $_[1] cmp $_[0]; } # $a and $b are not set here
    62. package main;
    63. @new = sort other::backwards @old;
    64. # guarantee stability, regardless of algorithm
    65. use sort 'stable';
    66. @new = sort { substr($a, 3, 5) cmp substr($b, 3, 5) } @old;
    67. # force use of mergesort (not portable outside Perl 5.8)
    68. use sort '_mergesort'; # note discouraging _
    69. @new = sort { substr($a, 3, 5) cmp substr($b, 3, 5) } @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 call find_records(@key) , you can use:

       
       
    1. @contact = sort { $a cmp $b } find_records @key;
    2. @contact = sort +find_records(@key);
    3. @contact = sort &find_records(@key);
    4. @contact = sort(find_records(@key));

    If instead you want to sort the array @key with the comparison routine find_records() then you can use:

       
       
    1. @contact = sort { find_records() } @key;
    2. @contact = sort find_records(@key);
    3. @contact = sort(find_records @key);
    4. @contact = sort(find_records (@key));

    If you're using strict, you must not declare $a and $b as lexicals. They are package globals. That means that if you're in the main package and type

       
       
    1. @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

       
       
    1. @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 well-defined.

    Because <=> returns undef when either operand is NaN (not-a-number), and laso because sort raises an exception unless the result of a comparison is defined, be careful when sorting with a comparison function like $a <=> $b any lists that might contain a NaN . The following example takes advantage that NaN != NaN to eliminate any NaN s from the input list.

       
       
    1. @result = sort { $a <=> $b } grep { $_ == $_ } @input;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值