施瓦茨變換(Schwartzian Transform)是一種排序思路。先看看它的結構:linux
my @output_data = map { EXTRACTION }, sort { COMPARISON } map [ CONSTRUCTION ], @input_data;
施瓦茨變換:app
先舉個例子,文件test.txt中的內容以下:函數
1 mac 2000 500 2 winxp 4000 300 3 bsd 1000 600 4 linux 1000 200 5 SUSE 4000 300 6 Debian 600 200
如今須要使用perl對該文件進行排序,以第三字段爲主排序依據(升序),第四字段(升序)、第一字段(降序)分別爲輔助排序依據。性能
下面這種代碼是誰都會的:優化
open DATA,"<","/perlapp/test.txt" or die "Can't open file: $!"; print sort { my @x = split / +/,$a; my @y = split / +/,$b; $x[2] <=> $y[2] or $x[3] <=> $y[3] or $y[0] <=> $x[0] } <DATA>;
上面的排序過程當中,對每一行都進行了一次split函數處理,換句話說,每一次比較操做都進行了兩次split。code
使用施瓦茨變換,能夠將每次比較過程當中每一種函數的屢次操做都減小爲一次,正如上面的split能夠減小爲一次(性能並無更優化,只是代碼減小了,更漂亮了)。orm
如下是使用Schwartzian Transform實現上述排序需求的代碼:排序
open DATA,"<","/perlapp/test.txt" or die "Can't open file: $!"; print map { $_->[0] } sort { $a->[3] <=> $b->[3] or $a->[2] <=> $b->[2] or $b->[1] <=> $a->[1] } map { [ $_,split / +/,$_ ] } <DATA>;
在上面施瓦茨變換代碼中(從下往上看):input
<DATA>
中的元素從新構建成了一個新的匿名列表A,這個列表中除了原始文件中的每一行數據,還有對每一行進行split後的元素,由於每一行都是空格分隔的,因此split後的每個元素都直接做爲匿名列表的元素。大概以下:["6 Debian 600 200","6","Debian","600","200"]