Perl自然排序数字

时间:2016-04-02 13:28:31

标签: perl sorting

我需要对数字进行排序,但我无法按照我想要的方式进行操作。

示例输入:

15.12
16.1
15.2
15.1

预期产出:

15.1
15.2
15.12
16.1

我尝试了正常的排序,也为此Sort::Naturally。两者都没有给我预期的输出。

我也知道我可以按照以下方式进行排序,以我想要的方式对其进行排序。

my @sorted =
map sprintf('%vd', $_),
sort
map join('', map chr, split /\./),
@data;

我想知道是否有一些我可以使用的预先存在的模块。

提前致谢。

4 个答案:

答案 0 :(得分:6)

如果我理解正确,您希望先按整数值对数字进行排序,然后将小数部分视为整数本身,因此.12大于.2,如示例所示(12 > 2)。

我认为最自我解释的方法是使用自定义排序,按照你所说的分割它们之后:

@sorted = sort {
    my ($a1, $a2) = split /\./, $a;
    my ($b1, $b2) = split /\./, $b;
    $a1 <=> $b1 or $a2 <=> $b2
} @numbers;

答案 1 :(得分:3)

您需要将(<=>)数字与特殊$a$b变量进行比较。请注意,您可以使用<=>替换cmp来对字符串执行相同操作。

use warnings;
use strict;

my @nums = qw(15.1 16.1 15.12);

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

print "$_\n" for @nums;

__END__
15.1
15.12
16.1

答案 2 :(得分:3)

您似乎正在尝试对版本号进行排序,其中每个组件都是独立排序的。排序::自然不会起作用,因为它忽略了非字母数字字符,但还有其他几个模块可以做到这一点。

Sort::Versions将其输入分为句点或连字符,并按字母顺序或数字顺序对每个组进行排序,具体取决于是否存在非数字字符:

use strict;
use warnings 'all';
use 5.010;

use Sort::Versions;

my @versions = (
    15.12,
    16.1,
    15.2,
    15.1
);

say for sort { versioncmp($a, $b) } @versions;

输出:

15.1
15.2
15.12
16.1

Sort :: Versions期望输入匹配某些常见的版本字符串格式;如果您需要对不同的格式进行排序,请检查文档中的规则以确保它适合您。

Sort::Key::Natural更灵活,因为它会分割所有单词边界,而不仅仅是句点和连字符,但在这种情况下它的作用相同:

use strict;
use warnings 'all';
use 5.010;

use Sort::Key::Natural qw(natsort);

my @versions = (
    15.12,
    16.1,
    15.2,
    15.1
);

say for natsort @versions;

(输出与Sort :: Versions相同)

Sort :: Key :: Natural有一些很好的附加功能,比如能够就地排序和自定义排序顺序。它在我的基准测试中也明显快于Sort :: Versions,尽管只有在你对大型数组进行排序时才会这么做。

答案 3 :(得分:1)

关于@stevieb 提供的答案,值“15.2”没有被删除:它在原始数组中丢失了。不过,运算符 <=>cmp 不可互换。它们分别用于比较数字和字符串。