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

时间:2014-02-19 04:51:30

标签: perl sorting hash key

我有这样的哈希

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)但它不起作用。

2 个答案:

答案 0 :(得分:4)

正如我在评论中所说,你不能对哈希进行排序,因为哈希不保留其键的顺序。但是,您可以对其键进行排序,并将其存储在保留顺序的内容中,如数组。为此,我们可以使用Schwartzian transform

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)恢复原始字符串并丢弃数组引用。

答案 1 :(得分:1)

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

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

当然你可以将排序的值存储在数组中而不是打印它们,但我认为这样输出可能更清楚。