2009-08-11
Perl–sort函数用法
sort函数用来对数组进行排序。用法如下:
#按字符排序
@articles=sort@files;
#按字符排序,显式说明
@articles=sort{$a cmp$b}@files;
#按字符排序,忽略大小写
@articles=sort{us($a)cmp uc($b)}@files;
#按字符排序,逆序
@articles=sort{$b cmp$a}@files;
#按数字顺序排序
@articles=sort{$a<=>$b}@files;
#按数字顺序排序,逆序
@articles=sort{$b<=>$a}@files;
#按散列的值排序
@eldest=sort{$age{$b}<=>$age{$a}}keys%age;
perl的sort函数
一)sort函数
sort LIST
sort BLOCK LIST
sort SUBNAME LIST
sort的用法有如上3种形式。它对LIST进行排序,并返回排序后的列表。假如忽略了SUBNAME 或BLOCK,sort按标准字串比较顺序来进行(例如ASCII顺序)。如果指定了SUBNAME,它实际上是个子函数的名字,该子函数对比2个列表元素,并返回一个小于,等于,或大于0的整数,这依赖于元素以何种顺序来sort(升序,恒等,或降序)。也可提供一个BLOCK作为匿名子函数来代替SUBNAME,效果是一样的。
被比较的2个元素,会被临时赋值给变量$a和$b。它们以引用传递,所以不要修改$a或$b。假
如使用子函数,它不能是递归函数。
(二)用法示例
1.以数字顺序sort
@array=(8,2,32,1,4,16);
print join('',sort{$a<=>;$b}@array),"\n";
打印结果是:
12481632
与之一样的是:
sub numerically{$a<=>;$b};
print join('',sort numerically@array),"\n";
这个很容易理解哦,它只是按自然数的顺序进行sort,偶就不细讲了。
2.1以ASCII顺序(非字典顺序)进行sort
@languages=qw(fortran lisp c c++Perl python java);
print join('',sort@languages),"\n";
打印结果:
Perl c c++fortran java lisp python
这等同于:
print join('',sort{$a cmp$b}@languages),"\n";
按ASCII的顺序进行排序,也没什么说的哦。
注意,如果对数字按ASCII顺序进行sort的话,结果可能与你想的不同:
print join('',sort1..11),"\n";
1101123456789
2.2以字典顺序sort
use locale;
@array=qw(ASCII ascap at_large atlarge A ARP arp);
@sorted=sort{($da=lc$a)=~s/[\W_]+//g;
($db=lc$b)=~s/[\W_]+//g;
$da cmp$db;
}@array;
print"@sorted\n";
打印结果是:
A ARP arp ascap ASCII atlarge at_large
use locale是可选的--它让code兼容性更好,假如原始数据包含国际字符的话。use locale影响了cmp,lt,le,ge,gt和其他一些函数的操作属性--更多细节见perllocale的man page。
注意atlarge和at_large的顺序在输出时颠倒了,尽管它们的sort顺序是一样的(sort中间的子函数删掉了at_large中间的下划线)。这点会发生,是因为该示例运行在perl5.005_02上。在perl版本5.6前,sort函数不会保护有一样values的keys的先后顺序。perl版本5.6和更高的版本,会保护这个顺序。
注意哦,不管是map,grep还是sort,都要保护这个临时变量$_(sort里是$a和$b)的值,不要去修改它。在该code里,在对$a或$b进行替换操作s/[\W_]+//g前,先将它们重新赋值给$da 和$db,这样替换操作就不会修改原始元素哦。
3.以降序sort
降序sort比较简单,把cmp或<=>;前后的操作数调换下位置就可以了。
sort{$b<=>;$a}@array;
或者改变中间的块或子函数的返回值的标记:
sort{-($a<=>;$b)}@array;
或使用reverse函数(这有点低效,但也许易读点):
reverse sort{$a<=>;$b}@array;
4.使用多个keys进行sort
要以多个keys来sort,将所有以or连接起来的比较操作,放在一个子函数里即可。将主要的比较操作放在前面,次要的放在后面。
#An array of references to anonymous hashes
@employees=(
{FIRST=>;'Bill',LAST=>;'Gates',
SALARY=>;600000,AGE=>;45},
{FIRST=>;'George',LAST=>;'Tester'
SALARY=>;55000,AGE=>;29},
{FIRST=>;'Steve',LAST=>;'Ballmer',
SALARY=>;600000,AGE=>;41}
{FIRST=>;'Sally',LAST=>;'Developer',
SALARY=>;55000,AGE=>;29},
{FIRST=>;'Joe',LAST=>;'Tester',
SALARY=>;55000,AGE=>;29},
);
sub seniority{
$b->;{SALARY}<=>;$a->;{SALARY}
or$b->;{AGE}<=>;$a->;{AGE}
or$a->;{LAST}cmp$b->;{LAST}
or$a->;{FIRST}cmp$b->;{FIRST}
}
@ranked=sort seniority@employees;
foreach$emp(@ranked){
print"$emp->;{SALARY}\t$emp->;{AGE}\t$emp->;{FIRST}
$emp->;{LAST}\n";
}
打印结果是:
60000045Bill Gates
60000041Steve Ballmer
5500029Sally Developer
5500029George Tester
5500029Joe Tester
上述code看起来很复杂,实际上很容易理解哦。@employees数组的元素是匿名hash。匿名hash实际上是个引用,可使用->;操作符来访问其值,例如$employees[0]->;{SALARY}可访问到第一个匿名hash里SALARY对应的值。所以上述各项比较就很清楚了,先比较SALARY的值,再比较AGE的值,再比较LAST的值,最后比较FIRST的值。注意前2项比较是降序的,后2项是升序的,不要搞混了哦。value函数什么意思
5.sort出新数组
@x=qw(matt elroy jane sally);