暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Perl基础函数---sort

EasyPerl 2021-06-30
1799

在日常程序中, 我们经常需要对数据进行排序, 以达到特定的要求。比如有些优化的算法, 都是先对数据进行排序, 然后再进行相关的操作的。


在Perl中,系统内置了一个功能强大的函数用来排序---sort。

sort 有3种用法,从简到繁:


sort LIST

sort BLOCK LIST

sort USERSUB LIST (今天暂时不介绍)


我们通过例子一个个来看,首先我们定义2个列表

my @nums = (1,5,3,2,7,55,44,4);
my @chars = ('a', 'cg', 'ddd', 'eg', 'f', 'sss', 'gggggg', 'cddd');

1. sort LIST

我们来对他进行排序

    

@nums = sort @nums; 
@chars = sort @chars;
如果需要反向排序, 则使用reverse方法即可
@chars = reverse sort @chars;

我们查看结果的时候会发现, 这边字符串数组如我们预期完全排序好了, 但是数字数组并不是我们所预期的, 因为sort默认的排序规则是根据标准字符串来进行比较的, 也就是 7是在55的后面的。所以, 默认排序的方法只适合字符串的简单排序。


2.sort BLOCK LIST

那我们如何对数字来进行排序呢, 我们一般使用第二种方法

@nums = sort { $a <=> $b } @nums; 
@chars = sort { $a cmp $b } @chars;

如果我们需要反向排序呢, 只需要$a $b对换一下位置即可。

我们来具体看下这个实现, 我们通过block{}代码块来定义排序的规则, sort要求返回大于,等于,小于3种结果, 因此在block代码块的最后返回语句, 往往是<=> 或者 cmp 运算符。<=>是针对数字的运算符, 相应的cmp等效于<=>, 只是作用对象为字符。

<=>这个运算符其实就是 <, =, >3个运算符的结合体, 用来在sort的block块中,返回数字之间的大小关系。 $a $b是固定的内置变量名,它们就是依次排序数据的别名, 不能替换它们, 也不要尝试去改变它们的值(这样会引发奇怪的结果),简单理解就是 $a理解为前面一个数据 $b为后面一个数据, 如果$a <=> $b 这样的顺序, 那么就是升序排序, 反之就是降序排序。 当然对于复杂的数据结构, 你使用的就不是 $a <=> $b, 而可能是含有$a $b的表达式。比如如果我们需要对hash来进行排序, 我们分别看下针对key和value的排序:

my %hash = ( a => 3,
c => 1,
b => 5,
           );


首先, 我们针对key来进行排序, 我们传给sort的是hash中所有key组成的数组, 并根据其值来进行排序

for (sort { $a cmp $b } keys %hash){
print "$_ => $hash{$_} \n";
}

接下来我们看如果根据值来进行排序,我们传给sort的仍然是hash中所有key组成的数组, 因此$a $b中存的仍然是key而不是我们要比较的value, 这个时候, 我们就需要对$hash{$a} $hash{$b}来进行比较了


for (sort { $hash{$a} <=> $hash{$b} } keys %hash){
print "$_ => $hash{$_} \n";
}


Block块中允许增加其他处理内容, sort只要求最后返回的是比较的结果, 也就是说, 一般只要求最后一句使用<=>/cmp来进行比较就可以。 


那么如果我们需要多个比较条件呢, sort支持多层比较, 即当第一个条件相同时, 比较第二个条件, 依次类推。 

比如我们需要对chars数据进行排序, 排序的规则是, 根据字符长度, 从长到短(降序)依次排序, 如果长度相同, 则根据标准字符顺序升序排序:

@chars = sort { 
length $b <=> length $a
                          ||
$a cmp $b
} @chars;

 我们只需要使用逻辑或运算符||来连接我们需要的比较条件即可, 可以根据需要使用任意多组比较条件, 来达到各种特殊的排序要求。


文章转载自EasyPerl,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论