数组的perl哈希 - 数字键的字母数字键?

时间:2011-11-11 10:12:10

标签: arrays perl sorting hash alphanumeric

据我所知,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”,但我也不能做数字排序!

2 个答案:

答案 0 :(得分: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$b,并以数字<=>而不是按字符串<=>对结果进行排序。此代码可以满足您的需求

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

但是如果您有大量数据,那么使用Schwartzian Transform可能会有利可图,这样可以避免每次比较时提取字符串的数字部分

  my @sorted = map  { $_->[0] }
               sort { $a->[1] cmp $b->[1] }
               map  { /.*_(.+)/ and [$_, $1] }
               keys %myhash;

答案 1 :(得分:0)

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

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

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;

另见@ Borodin的回答。