我有一个看起来像这样的哈希
my %hash = (
'124:8' => '',
'4:2' => '',
'17:11' => '',
'17:0' => '',
#and so on
);
我尝试排序并使用小数字到更大的哈希键
for my $keys ( sort { $a > $b } keys %hash ) {
#do stuff
}
这给了我一些看似正确的结果,但有时会失败。我不知道如何将这两个数字124:8
与4:2
进行比较,因为它中间有:
,有什么建议吗?
答案 0 :(得分:4)
对数字进行排序时,使用<=>
运算符:
for my $key (sort { $a <=> $b } keys %hash) {
此运算符根据比较返回1,0或-1。 >
只返回true或false,这解释了它使用了一些结果,但不是全部。
由于您的密钥不是数字,因此它们只会部分转换为数字,您将收到警告
Argument "17:11" isn't numeric in sort
然后你需要使用类似Sort::Key::Natural
的东西,或者摆动自己的东西,例如:
sort {
my @a = $a =~ /\d+/g;
my @b = $b =~ /\d+/g;
$a[0] <=> $b[0] ||
$a[1] <=> $b[1] # continue as long as needed
} keys %hash
您也可以使用Schwartzian transform来缓存数字,并可能加快排序速度。
或者只是按字符串比较排序,但这会导致17:11
在17:2
之后结束。
答案 1 :(得分:4)
您可能希望对按:
my @sorted = sort {
my ($aa, $bb) = map [ split /:/ ], $a, $b;
$aa->[0] <=> $bb->[0] || $aa->[1] <=> $bb->[1]
} keys %hash;
for my $key (@sorted) { .. }
使用Schwartzian,
my @sorted = map $_->[0],
sort {
$a->[1] <=> $b->[1] || $a->[2] <=> $b->[2]
}
map [ $_, split /:/ ],
keys %hash;
答案 2 :(得分:0)
不如上述解决方案那么优雅,但是将:
转换为.
并将它们作为浮点数进行比较的内容是什么?因为没有数学运算,所以没有舍入错误,下一个可以工作:
my %tmp = map { (my $x = $_) =~ s/:/./; $_,$x} keys %hash;
my @sortedkeys = sort { $tmp{$a} <=> $tmp{$b} } keys %tmp;
#4:2 17:0 17:11 124:8
或者这种做法是错误的?