使用perl进行字母数字排序

时间:2016-03-18 13:18:08

标签: arrays perl sorting

@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

5 个答案:

答案 0 :(得分:8)

为什么重新发明轮子?

只需use Sort::Naturally

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