据我所知,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”,但我也不能做数字排序!
答案 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)
您需要进行自定义排序:将您的字符串剪切为知道是文字/数字的部分,然后根据需要进行比较。
从您的示例中看起来您想要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;
另见@ Borodin的回答。