由浅入深谈Perl中的排序

主要内容:

1. 简单的使用sort排序

2. 对哈希按键排序

3. 对哈希按值排序

4. 对数组的数组排序

5. 使用Schwartzian Transform 排序

6. 对矩阵按多列排序

Perl中排序主要用sort函数,sort函数可以对列表按字母表顺序或者数值顺序进行排序,并返回排序好的列表,但是,请注意,sort不会改变原列表的值和顺序。sort函数进行排序用法如下:

sort SUBNAME LIST

sort BLOCK LIST

sort LIST

下面会分别介绍sort排序的应用。

1. sort简单排序

如果只是简单地排序,直接使用上面用法的模式三即可。sort简单排序只会对列表内容按ASCII码排序。

【例】 my @arr = sort qw(map 23 Perl 101 11 while 1 scalar 102);

print “@arr\n”;

# output: 1 101 102 11 23 Perl map scalar while

由于sort简单排序只能按alphabetical order排序,所以有时不能满足用户需求。为此,我们可以使用用法模式一和二。如用cmp和<=>操作符等。

sort { $a <=> $b} @arr; #对数组按数值升序排列

sort {$a cmp $b} @arr; # 对数组值按字符比较顺序升序排列

2. 对哈希按键排序

【例】

my %hash = (one => 1, two => 2, three => 3, four => 4);

#通常哈希不会按顺序输出没对键-值对,所以,要经过排序

foreach my $key (sort keys %hash){

print “$key: $hash{$key}\n”;

}

#It produces the following output:

four: 4

one: 1

three: 3

two: 2

3. 对哈希按值排序

仍然以上个hash为例:

【例】

foreach ( sort { $hash{$a} <=> $hash{$b} } keys %hash )

{

print “$_: $hash{$_}\n”;

}

4. 对数组的数组进行排序

这里主要说的是对子数组按数值或字母ASCII排序。

【例】 my @AOA = ([25,49,33,100], [145,87], [11, 85, 78]);

foreach my $item1 ( @AOA ){

foreach my $item2 ( sort { $b <=> $a } @{$item1} ){

print “$item2\t”;

}

print “\n”;

}

#输出:

100 49 33 25

145 87

85 78 11

5. 使用Schwartzian Transform 排序

在讲Schwartzian Transform 排序前,咱先学习下面几个函数:

(1) map函数:转换一个数组,即对一个数组的每个元素做block或者express里的运算,然后返回新的数组(详细介绍请查看后面章节)。

这节我们讨论对二维数组的某一列进行排序,如下面的例子:

my $str = “ three 13 3 1 91 3

one 11 5 1 45 1

two 12 7 1 33 2

four 14 1 1 26 4”;

$str = join “ “,

map { $_->[0]. “\n” }

sort { $a->[1] <=> $b->[1] }

map { [$_, (split)[-1]] }

split /\n/, $str;

print $str, “\n”;

① split /\n/, $str;

此表达式对字符串$str进行分割,得到一个数组,含四个元素。然后该数组作为参数传递给上面的map函数。

② map { [$_, (split)[-1] ] }

这里map对上一表达式传来的数组进行转换,参数保存到默认变量$_中;split没有加参数,所以也对默认变量$_按“ ”进行分割,由于split函数返回一个匿名数组,所以(split)[-1]表示分割后数组的最后一个元素。这样map 结果也是返回一个匿名数组,且该数组的每个元素也是一个包含两个元素$_ 和(split)[-1]的数组。然后传递给sort函数做排序处理。