施瓦茨变换(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"]