对用连字符分隔的数字哈希键进行排序



我有一个这样的哈希

my %hash = (
            '2011-49' => 'data1',
            '2011-100' => 'data2',
            '2009-22' => 'data3',
            '2011-11' => 'data4',
            '4323' => 'data5',
            '2354' => 'data6',
            '423532-2' => 'data7'
           );

如何对哈希键进行排序,以便它根据第一个数字进行排序,然后根据显示以下输出的第二个数字进行排序。

my %hash = (
            '2009-22' => 'data3',
            '2011-11' => 'data4',
            '2011-49' => 'data1',
            '2011-100' => 'data2',
            '2354' => 'data6',
            '4323' => 'data5',
            '423532-2' => 'data7'
           );

我按下数组中的所有键并使用排序 Sort::Naturally qw(nsort ncmp) 但它不起作用。

正如我在评论中所说,您无法对哈希进行排序,因为哈希不会保留其键的顺序。但是,您可以对其键进行排序并将它们存储在保留顺序的东西中,例如数组。为此,我们可以使用施瓦茨变换:

my @sorted_keys = map $_->[0],                           # 3)
                  sort { $a->[1] <=> $b->[1] ||          
                         $a->[2] <=> $b->[2] }           # 2)
                  map { [ $_, /(d+)/g ] } keys %hash;   # 1)

从最后开始,我们 1) 首先将原始字符串以及第一个和第二个数字存储在匿名数组 ref 中。结果是一个数组引用列表 - 一个缓存 - 我们 2) 传递给 sort ,在那里它们首先根据第一个数字进行排序,如果它们相同,则根据第二个数字进行排序。这是通过在sort代码块中使用||来实现的。最后,我们 3) 恢复原始字符串并丢弃数组引用。

你已经得到了一个很好的答案,但我想我会权衡一下 Sort::Versions。 这似乎比 Sort::Natural 更好地处理这些类型的操作:

use warnings;
use strict;
use Sort::Versions;
my %hash = (
            '2011-49' => 'data1',
            '2011-100' => 'data2',
            '2009-22' => 'data3',
            '2011-11' => 'data4',
            '4323' => 'data5',
            '2354' => 'data6',
            '423532-2' => 'data7'
);
print "$_ => $hash{$_}n" for ( sort{ versioncmp( $a, $b ) } keys %hash );

这将产生以下输出:

2009-22 => data3
2011-11 => data4
2011-49 => data1
2011-100 => data2
2354 => data6
4323 => data5
423532-2 => data7

当然,您可以将排序后的值存储在数组中而不是打印它们,但我认为以这种方式输出可能更清晰。

最新更新