如果给出了 USERSUB,那么它就是一个返回小于,等于,或者大于 0 的整数的子过程名字,具体返回什么取决于列表中的元素应该如何排序。(很便利的 和 cmp 操作符可以用于执行三向数字和字串比较。)如果给出了 USERSUB,但该函数未定义,那么 sort 抛出一个例外。
为了提高效率,绕开了通常用于子过程的调用代码,这样就有了下面的结果:这个子过程不能是递归子过程(你也不能用一个循环控制操作符退出该块或者过程),并且将要接受比较的两个元素不是通过 @_ 传递进子过程的,而是通过临时设置 sort 编译所在的包的全局变量 $a 和 $b(参阅后面的例子)。变量 $a 和 $b 是真实值的别名,所以不要在子过程中修改它们。
子过程要求的动作是比较。如果它返回的结果是不一致的(比如,有时候说 $x[1] 小于 $x[2],而有时候说的正相反),那么结果就不会良好。(这也是你不能修改 $a 和 $b 的另外一个原因。)
USERSUB 可以是标量变量名字(未代换),这时,它的值要么是引用实际子过程的符号引用,要么是硬引用。(符号名更好些,即使用了 use strict 'refs' 用法也如此。)在 USERSUB 的位置,你可以提供一个 BLOCK 用做一个匿名内联排序子过程。
要做一次普通的数字排序,你可以说:
sub numerically { $a <=> $b }
@sortedbynumber = sort numerically 53, 29,11,32, 7;
要以降序排序,你可以简单地在 sort 后面应用 reverse,或者你可以在排序过程里把 $a 和 $b 反过来:
sub numerically { $a <=> $b }
@sortedbynumber = sort numerically 53,29,11,32,7;
@descending = reverse sort numerically 53,29,11,32,7;
sub reverse_numerically { $b <=> $a }
@descending = sort reverse_numerically 53,29,11,32,7;
要对字串进行大小写不敏感的排序,在比较之前用 lc 处理 $a 和 $b:
@unsorted = qw/sparrow Ostrich LARK catbird blueJAY/;
@sorted = sort { lc($a) cmp lc($b) } @unsorted;
(在 Unicode 里,用 lc 做大小写规范化要比用 uc 好,因为有些语言里抬头体和大写是不一样的。不过它对普通的 ASCII 排序没有什么影响,并且如果你想让 Unicode 能正确排序,那么你的规范化过程可能要比 lc 更别致一些。)
对散列按照数值排序是 sort 函数的常用法之一。比如,如果 %sales_amount 散列记录部门销售情况,那么在排序过程里做一次散列查找就可以让我们将散列键字根据它们的数值排序:
# 从销售额最高的部门到最低的部门
sub bysales { $sales_amount{$b} <=> $sales_amount{$a} }
for $dept (sort bysales keys %sale_amount) {
print "$dept => $sales_amount{$dept}\n";
}
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-28372-8.html
自己什么都不需要担心