1

我知道 Perl 中的默认排序是 ASCII 排序,而不是数字。但是我怎样才能对有数字的字符串进行数字排序呢?

例如,我有一个数组哈希,如下所示:

myhash{ANN20021015_0101_XML_71.9} = ("anta", "hunna", "huma");
myhash{ANN20021115_0049_XML_14.1} = ("lqd", "qAl", "arrajul");
myhash{ANN20021115_0049_XML_14.2} = ("anna", "alwalada");

我只需要对键进行排序......但排序是字符串中的数字。我不能进行字符串排序,因为我在“1”之后得到了“10”,但我也不能进行数字排序!

4

2 回答 2

6

首先,您的代码不是有效的 Perl,并且可能不会像您认为的那样做。总是

  use strict;
  use warnings;

在你的程序的头部解决任何简单的错误。代码应该看起来像

  $myhash{'ANN20021015_0101_XML_71.9'} = ["anta", "hunna", "huma"];
  $myhash{'ANN20021115_0049_XML_14.1'} = ["lqd", "qAl", "arrajul"];
  $myhash{'ANN20021115_0049_XML_14.2'} = ["anna", "alwalada"];

要对整个值以外的内容进行排序,您可以在排序块内转换$a和排序,并以数字方式而不是 stringwise对结果进行排序。此代码可以满足您的需要$b<=><=>

  my @sorted = sort {
    my ($aa) = $a =~ /.*_(.+)/;
    my ($bb) = $b =~ /.*_(.+)/;
    $aa <=> $bb;
  } keys %myhash;

但是,如果您有大量数据,则使用Schwartzian 变换可能是有利可图的,这将避免在每次比较字符串时提取字符串的数字部分

  my @sorted = map  { $_->[0] }
               sort { $a->[1] cmp $b->[1] }
               map  { /.*_(.+)/ and [$_, $1] }
               keys %myhash;
于 2011-11-11T10:54:02.627 回答
0

您需要进行自定义排序:将您的字符串切割成您知道是文字/数字的部分,并根据需要进行比较。

从您的示例中,它看起来像您想要literal的。digits,但您可以更改正则表达式以使其适合您。

my $cut = qr/(.*?\.)(\d+)(.*)/;
sort { 
    my @a = $a =~ $cut; my @b = $b =~ $cut; 
    $a[0] cmp $b[0] || $a[1] <=> $b[1] || $a[2] cmp $b[2] 
} keys %myhash;

另见鲍罗丁的回答

于 2011-11-11T11:05:49.020 回答