@arr = qw(test1 test3 tes5 test2 test4 test8 test6 test7 test10 test9);
如何对此数组进行排序并获得如下输出:
test1 test2 test3 test4 test5 test6 test7 test8 test9 test10
而不是
test1 test10 test2 test3 test4 test5 test6 test7 test8 test9
答案 0 :(得分:8)
use strict;
use warnings;
use feature 'say';
use Sort::Naturally 'nsort';
my @test = map 'test'.$_, reverse 1..10;
say for nsort @test;
打印
test1
test2
test3
test4
test5
test6
test7
test8
test9
test10
答案 1 :(得分:1)
使用自定义排序子例程:
my @arr = qw(test1 test3 tes5 test2 test4 test8 test6 test7 test10 test9);
foreach ( sort { number_strip($a) <=> number_strip($b) } @arr ){
say;
}
sub number_strip {
$line = shift;
my ($num) = $line =~ /(\d+)/;
return $num;
}
test1
test2
test3
test4
tes5
test6
test7
test8
test9
test10
答案 2 :(得分:0)
将字符串拆分为排序比较器并逐个检查一个元素。 $ta
代表来自a
的文字,$na
是数字,$ra
是字符串的其余部分(如果有的话):
@result = sort({
my ( $ta, $na, $ra ) = $a =~ m/^(.*?)(\d+)(.*)$/;
my ( $tb, $nb, $rb ) = $b =~ m/^(.*?)(\d+)(.*)$/;
return $ta cmp $tb || $na <=> $nb || $ra cmp $rb;
}
@arr
);
答案 3 :(得分:0)
my @sorted = map { s/(^|\D)0+(\d)/$1$2/g; $_ } sort
map { /(\d+)/sprintf("%06.6d",$1)/ge; $_ } @arr;
会自然地对您的数组进行排序。另外我注意到你的初始描述中没有 test5 元素,但是 tes5 而不是
有待解释,这可以分为几部分。因为Perl解释器从右到左抓取表达式,所以第一个动作是
my @sorted = map { s/(\d+)/sprintf("%06.6d",$1)/ge } @arr;
这里我们在文本和数字之间添加零,以便有6个小数位(这是一个随机数,可以是任何满足当前任务的数字)
然后我们用词法排序数组
@sorted = sort @sorted
然后删除插入的零
@sorted = map { s/(^|\D)0+(\d)/$1$2/g } @sorted;
主要警告 - 这会打破像&test;&#39;
; 这样的元素答案 4 :(得分:0)
如果您更愿意避开该模块,那么您可以编写一个排序块,将每个字符串拆分为alpha部分和数字部分,并分别对它们进行比较。
但是这依赖于格式始终为AAA999
,而且如果格式在将来发生变化,我会更喜欢Sort::Naturally
请注意,您的示例数据存在虚假tes5
,我认为这是一个错字,但仍然可以作为测试数据。它在所有其他值之前排序,因为tes
在词法test
之前排序
use strict;
use warnings 'all';
use feature 'say';
my @arr = qw(test1 test3 tes5 test2 test4 test8 test6 test7 test10 test9 );
say for sort {
my ($aa, $bb) = map [ /([a-z]+)(\d+)/i ], $a, $b;
$aa->[0] cmp $bb->[0] or $aa->[1] <=> $bb->[1];
} @arr;
tes5
test1
test2
test3
test4
test6
test7
test8
test9
test10