你告诉Perl 你要的顺序,通过排序定义(sort-definition)的子程序。Perl 知道如何将元素排序,但它不知道你想要什么样的排序。因此排序子程序告诉它你要的顺序。
为什么要这么做呢?如果你想象一下,排序是将一些东西通过比较按顺序排列。由于一次不能将所有的元素进行比较,你需要一次比较两个元素,最终通过这两个元素的比较结果,来得到最终的结果。Perl 了解这一切,除了不知道你想怎样比较这两个元素,那就是需要你写的。这意味着排序子程序不需要对大量的元素进行排序。事实上只需要比较两个元素。如果能将两个元素按恰当的顺序排序,Perl 则能够知道(重复的访问排序子程序)你想如何排序这些数据。排序子程序被定义成普通的子程序一样(恩,是的,几乎一样)。这个子程序会被重复的调用,每一次检查一对你需要排序的列表元素。
- #!/usr/bin/perl
-
#
-
sub by_number{
-
if($a < $b){1}
-
elsif($a > $b){-1}
-
else{0}
-
}
-
-
@number = (3,4,6,0,10);
-
my @re = sort by_number @number;
-
-
print "@re\n";
-
#10 6 4 3 0
、要使用一个排序子程序,将它(不使用&)放在关键字sort 和你要排序的列表之间。
我们不需要在排序子程序中申明$a 和$b,以及给它们设置。如果做了,子程序将不能得到正确结果。我们让Perl 为我们给$a 和$b 赋值,我们只需要写如何比较。事实上,我们可以使之更简单,效率也更高。因为这种三向的比较(three-way comparison)使用很频繁,Perl 提供了一种方便的简写方式。针对本例,我们使用太空船(spaceship)符号(<=>)。
事实上,我们可以使之更简单,效率也更高。因为这种三向的比较(three-way comparison)使用很频繁,Perl 提供了一种方便
的简写方式。针对本例,我们使用太空船(spaceship)符号(<=>)◆。这个操作符比较两个数字,按照数字将其排序,并
返回-1, 0, 1。因此,我们可以将排序子程序,写成下面更好的方式:
◆我们这样叫它的原因是,因为它很像星球大战(Star Wars)中的Tie-fighters。是的,我们觉得它们很像。
sub by_number {$a <=> $b }
由于这个太空船符号(<=>)比较数字,你可能猜想有一个对应的针对字符串的三向操作符:cmp。这两个操作容易记忆和使
用。<=>操作符有类似的数字比较符,如>=,但它(<=>)是三个而非两个字符长,因为它有三个而非两个可能的返回值。而
cmp 操作符有些类似于字符串比较操作符如ge,但它是三个而非两个字符长,因为它有三个而非两个可能的返回值◆。当
然,cmp 的顺序和默认的排序顺序是一样的。你不需要书写这些子程序,因为它们几乎都是默认的排序顺序◆:
◆这不是巧合。Larry 作事总是带有目的的,让Perl 易于学习和记忆。他是一个语言学家,因此他研究过人们如何思考语言。
◆你决不会写这些,除非你写一个初级的Perl 教本,需要将它作为一个例子。
sub ASCIIbetically {$a cmp $b} my @string = sort ASCIIbetically @any_strings;
也可以使用cmp 来创建更复杂的排序,如大小写无关的排序:
sub case_insenstive {“\L$a”cmp “\L$b”}
这里,我们比较两个字符串$a(强制转变成小写)和$b(强制转变成小写),给出一个大小写无关的排序。
我们没有修改这些数据本身,我们使用它们的值。这非常重要:出于效率的考虑,$a 和$b 不是这些数据的副本。它们是这
些原始数据的新的,临时别名,因此如果修改了它们,则会破环原始的数据。不要那样做,这几乎不被支持,也不被推荐。
当你的排序子程序像我们这里的那样简单时(大多数时候,是这样的),你可以通过使用“in line”子程序来代替排序的名字,
使之更简单,如:
my @numbers = sort { $a <=> $b } @some_numbers;
在当代的Perl 程序中,几乎见不到独立的排序子程序,你常见到的是像我们这里的那样:in line。
假设想按照数字的降序方式排序,这通过使用reverse 能很容易的做到:
my @descending = reverse sort { $a <=> $b } @some_numbers;
这里有一个技巧。比较操作符(<=>和cmp)是很“近视的”,它们不知道哪一个操作数是$a,哪一个是$b。它们只知道哪
一个值在左边,哪一个在右边。如果$a 和$b 交换位置,比较操作符每一次得到的结果则是相反的。这意味着另一种得到逆
序的方式:
my @descending = sort {$b <=> $a } @some_nubmers;
通过少许的练习,你可以容易的阅读这些代码。它是一个降序比较(因为$b 在$a 之前,这表示降序),它是数字比较(因
为它使用的是<=>而非cmp)。因此,这是一个按相反方向的数字排序。在当代的Perl 版本中,使用哪一种方法无关紧要,
因为reverse 被当作sort 的一个修饰符,特殊的简写方式阻止你使用一种方式排序但得到的却是另一种结果。
阅读(551) | 评论(0) | 转发(0) |