Perl學習筆記之Sort

說起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的精妙吧!



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章