发布于2026-06-29 阅读(0)
扫一扫,手机访问
今天我们来聊聊Perl中的数组排序,特别是针对字符串和数字。排序可以说是日常开发中最常见的需求之一,Perl内置的sort函数用起来相当顺手,但如果不了解它的默认行为,偶尔也会踩坑。下面我们一步步把各种场景讲清楚。

先看最基础的情况:直接给sort传一个数组,它会返回一个排序后的新数组,原数组不会被改变。写法简单到不能再简单:
@sorted = sort @original;
基于ASCII码排序
来个实际例子:
#!/usr/bin/perl
use strict;
use warnings;
use 5.010;
use Data::Dumper qw(Dumper);
my @words = qw(foo bar zorg moo);
say Dumper @words;
my @sorted_words = sort @words;
say Dumper @sorted_words;
运行后会输出排序前的数组和排序后的结果:
$VAR1 = [
'foo',
'bar',
'zorg',
'moo'
];
$VAR1 = [
'bar',
'foo',
'moo',
'zorg'
];
看起来挺正常?但假如数组中有些单词是大写字母开头的呢?比如把zorg改成Zorg:
my @words = qw(foo bar Zorg moo);
排序后结果会变成:
$VAR1 = [
'Zorg',
'bar',
'foo',
'moo'
];
咦?大写开头的Zorg居然排到了最前面。这就是因为sort默认按ASCII码表排序,而所有大写字母的码值都比小写字母小,所以它们自然排到了小写前面。
比较函数
其实sort的工作方式很有趣:它会遍历原始数组,每次取两个元素,把左边的值放进变量$a,右边的放进$b,然后调用一个“比较函数”。这个函数返回1表示$a应该放左边,返回-1表示$b应该放左边,返回0表示两者相等。默认的比较函数是cmp,它专门比较字符串,按ASCII顺序给出结果。
你可能会问:既然默认就是cmp,那我能不能显式写出来?当然可以,效果完全一样:
sort { $a cmp $b } @words;
这里的花括号就是比较函数块。Perl会替你处理好一切,你只需要告诉它用cmp比较两个值。
按字母顺序排列
如果希望忽略大小写,真正按字母顺序排序(比如把“Zorg”放在“bar”之后),那就在比较函数里把两个字符串都转成小写再比较:
my @sorted_words = sort { lc($a) cmp lc($b) } @words;
调用lc把值转成小写,再让cmp比较,这样大小写差异就被抹平了。结果如下:
$VAR1 = [
'bar',
'foo',
'moo',
'Zorg'
];
注意原始字符串的大小写仍然保留——Zorg依然是大写的,只是排序时参考了它们的小写版本。
Perl对数值排序
说完了字符串,那数字呢?直接套用默认sort会出大问题:
my @numbers = (14, 3, 12, 2, 23);
my @sorted_numbers = sort @numbers;
say Dumper @sorted_numbers;
输出结果:
$VAR1 = [
12,
14,
2,
23,
3
];
12竟然排到了2的前面?别惊讶,因为sort始终把它们当作字符串处理。“12”的第一个字符是“1”,“2”的第一个字符是“2”,“1”在ASCII表上排在“2”前面,所以“12”就跑到“2”前面去了。Perl可不会自作主张猜你想按数字排序。
那数字排序怎么办?用宇宙飞船操作符<=>,它专门用来比较数字,返回1、-1或0:
my @sorted_numbers = sort { $a <=> $b } @numbers;
这次终于对了:
$VAR1 = [
2,
3,
12,
14,
23
];
总结一下:字符串排序默认用cmp,按ASCII码;想忽略大小写就加上lc;数字排序要用<=>。记住这几个核心点,Perl的数组排序基本就能玩转了。
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
售后无忧
立即购买>office旗舰店
正版软件
正版软件
正版软件
正版软件
正版软件
1
2
3
7
8