說起Perl的Sort,自然會想到她的精巧,第一次體會到Perl的魅力就是看到她的精巧。
首先說明下sort的一些注意點,默認以UTF-8方式排序,默認的兩個操作符是$a 與 $b
下面,就從最簡單的sort形式講起,
my @sortted_list = sort {$a <=> $b}@list
這一句就將@list按從小到大的方式排序後賦值給@sortted_list,$a和$b表示當然,這是對於數字來說,如果是字符的話,就要這樣:
my @sortted_list = sort {$a cmp $b}@list
用“cmp”即可
對於Perl的排序中的{$a <=> $b},就相當於比較的子函數,它在排序的過程中會不斷調用這個子函數來得出比較結果。相信大家用過C的sort函數時知道它有回調函數的參數的吧?
然後,還可以對參數進一步操作,比如,我可以進行大小寫無關的排序
my @sortted_list = sort {lc $a cmp lc $b}@list
其中的lc表示lower函數,即轉爲小寫
還可以對哈希數組排序
sort {$hash{$a} <=> $hash{$b}}keys %hash
甚至,按照多個鍵的先後順序排序
比如下面這段:
my @x = qw(a a b a b c);
my @y = qw(a b c d e f);
my @z = sort{
$x[$a] cmp $x[$b]
or
$y[$a] cmp $y[$b]
}0..$#x;
就表示先按x排序,然後按y排序,其中$#x表示@x的長度
然後,來就說下高級排序:
首先,我有這樣的數據:
n多行,每一行的數據以:作爲分隔符,有兩個分隔符,相當於每行有3個字段
以第三個字段排序
然後最簡單的做法:
my sortted_list = sort{(split /:/ , $a)[2] <=> (split /:/)[2] , $b }@list;
顯然,效率不行,每次調用子程序的次數是n*log(n),好吧,現在加入緩存
my %lines = map{$_,(split /:/)[2]}@list;
my sortted_list = sort{$lines{$a} <=> $lines{$b}}keys %lines;
現在看起來不錯了,但是,還有更酷的做法
先了解下這個操作符: "||=",聯繫下“+=”這些操作符號就不難理解了,對於$a ||= $b來說,就相當於$a = $a || $b,解釋就是$a 沒有定義的話就將$b的值賦給$a
於是,利用這個特性,我們就可以寫出更酷的語句:
my %hash;
my sortted_list = sort{$hash{$a} ||= (split /:/ , $a)[2] <=> $hash{$a} ||= (split /:/)[2] , $b }@list;
這個做法有一個專門的名稱,稱爲Orcish Maneuver或者,|| cache
還有更精簡的做法:
my @sortted_list =
map{$_->[0]}
sort{$a->[1] <=> $b->[1]}
map{[$_,(split /:/)[2]}@list;
迷糊了吧,這句來自於3條語句,依次從下到上執行,每一句的結果都是上一句的參數
它也有個專門的名字,施瓦辛格變換,這個那個電影明星應該沒關係。。。
好了,就到這裏,體會Perl的精妙吧!