Chinaunix首页 | 论坛 | 博客
  • 博客访问: 45181
  • 博文数量: 43
  • 博客积分: 1161
  • 博客等级: 少尉
  • 技术积分: 425
  • 用 户 组: 普通用户
  • 注册时间: 2010-04-24 11:14
文章分类
文章存档

2011年(40)

2010年(3)

分类: Python/Ruby

2011-04-26 01:08:13

Perl内置sort以ASCII码序对列表排序.
Perl允许建立自己的排序规则子程序,或简称排序子程序来实现想要的排序方式.
这里的排序子程序不是数据结构中的冒泡排序,希尔排序等,Perl知道怎么对列表排序,只是不知道要用什么样的规则,所以排序子程序只是用来说明具体的规则.
排序子程序并不需要比较许多元素,只要能比较两个元素就行.
  1. #!/usr/bin/perl
  2. use strict;
  3. use5.010;
  4. sub any_sort_sub {
  5.   my($a,$b)=@_;
  6.   ......
  7. }
实际上这么写不能正确工作,这里只是为了方便说明问题.子程序内声明了两个变量并给它们赋值,然后开始比较$a和$b.
排序子程序会一次次地被调用,往往运行很多次,在子程序开始的地方声明变量$a和$b并给它们赋值,看起来只会花一点时间,但是把这些时间乘以排序子程序可能被调用的次数,就可以看出,这对整体性能会造成不小的影响.
实际写排序子程序并不会这么做.在子程序开始之前,Perl已经办好了这些事情.实际写出的排序子程序并不会有例子中的第5行,$a和$b都已经被自动赋值好了.当排序子程序开始运行时,$a和$b会是两个来自原始列表的元素(顺序什么的不需要考虑了).
假如在结果列表中$a应该在$b之前,排序子程序就会返回-1;如果$b应该在$a之前,它就会返回1;如果$a与$b的先后不必区分,则返回0.
飞碟操作符(<=>)
  1. #!/usr/bin/perl
  2. use strict;
  3. use 5.010;
  4. sub by_number {
  5.   if($a<$b) {
  6.     return-1;
  7.   }elsif($a>$b) {
  8.     return1;
  9.   }else{
  10.     return0;
  11.   }
  12. }
  13. my @org=qw(12 4 5 7 3 9 6);
  14. my @cur=sort by_number @org;
  15. say "@cur";
程序为了让数字从小到大排序,实现了子程序by_number.
程序的第5行刀第11行,根据Perl排序子程序的工作规则来看:
如果$a<$b,则$a在$b之前.
如果$a>$b,则$a在$b之后.
如果$a==$b,则位置不动.
这样写在Perl看来太麻烦了,所以有更加简便的写法:
  1. #!/usr/bin/perl
  2. use strict;
  3. use 5.010;
  4. sub by_number {
  5.   $a<=>$b;
  6. }
  7. my @org=qw(12 4 5 7 3 9 6);
  8. my @cur=sort by_number @org;
  9. say "@cur";
程序中第5行完全能代替前面程序第5~11行的功能.
也就是说,飞碟操作符(<=>)的功能就是让Perl知道,$a在什么情况下会排在$b的前面.
$a<=>$b表示:$a较小时,$a在$b之前.
$b<=>$a表示:$b较小时,$a在$b之前.
-1
<=>
根据这个表,可以这么来读表达式 $a<=>$b:
$a<$b时,表达式返回-1.($a在前面)
$a=$b时,表达式返回0.
$a>$b时,表达式返回1.($a在后面).
所以表达式是按递增排序.
同理来读 $b<=>$a,会知道是按递减排序.

飞碟操作符(<=>)专门用来处理数字,在Perl中还有个与飞碟操作符的逻辑完全一样,专门用来处理字符串的操作符:cmp

如果排序规则很简单,就不需要把规则独立写成一个子程序,可以内嵌到排序语句中:
  1. #!/usr/bin/perl
  2. use strict;
  3. use 5.010;
  4. my @org=qw(12 4 5 7 3 9 6);
  5. my @cur=sort {$a<=>$b} @org;
  6. say "@cur";

按多值排序
假设有一个哈希,key为人名,value为每人的分数.现在要把哈希按分数从小到大排序,如果分数一样,则按名字的ASCII顺序排.
  1. #!/usr/bin/perl
  2. use strict;
  3. use 5.010;
  4. my %score=("barney"=>195,
  5.   "fred"=>205,
  6.   "dino"=>30,
  7.   "john"=>67,
  8.   "ada"=>30,
  9. );

程序的第11,12行实现了按多值排序.
多值排序基于两个概念实现:
  1. Perl任务0为FALSE,非0为TRUE.
  2. 逻辑表达式具有短路特性.
在Perl的排序子程序中,$a==$b时会返回0,所以如果分数相等,第11行表达式返回0,在逻辑表达式中Perl认为是FALSE.需要执行第12行来确定整个表达式的值.如果分数不相等,第11行表达式的值为1/-1,Perl认为是TRUE,不需要判断or之后表达式的值了.
这就实现了按多值排序.
子程序by_value中的or可以根据实际情况写很多个.
阅读(333) | 评论(0) | 转发(0) |
0

上一篇:文件句柄

下一篇:怎么写POD

给主人留下些什么吧!~~