【问题标题】:sorting numeric hash keys separated by hyphen排序由连字符分隔的数字哈希键
【发布时间】:2014-03-19 05:50:27
【问题描述】:

我有一个这样的哈希

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) 但是不行。

【问题讨论】:

  • 您不能对哈希进行排序,哈希不存储其键的顺序。不过,您可以对键进行排序并将它们放入一个数组中。
  • @TLP 我做了同样的事情,将数组放入 n 排序
  • 那么你的问题不是如何对哈希进行排序,而是如何对键进行排序。
  • 是的,我在我的问题中指出了这一点。
  • 是的,但是您显示了存储在哈希中的排序键。这是不可能的。所以我只是想澄清一下。

标签: perl sorting hash key


【解决方案1】:

正如我在 cmets 中所说,您无法对哈希进行排序,因为哈希不保留其键的顺序。但是,您可以对其键进行排序并将它们存储在保持顺序的东西中,例如数组。为此,我们可以使用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) 恢复原始字符串并丢弃数组 refs。

【讨论】:

  • 您能解释一下施瓦茨变换的工作原理吗?我已经阅读了维基百科,但无法理解编码部分。
  • 答案中有说明。在这里使用它并不重要,但它使代码更干净,IMO。基本上,这是一种使用缓存来避免在排序期间重复昂贵操作的方法。您将排序中使用的数字存储在数组列表中,进行排序,然后恢复原始字符串。
  • 上次编辑清除关于施瓦茨变换的图片。
【解决方案2】:

您已经得到了一个很好的答案,但我认为我会权衡 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

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

【讨论】:

    猜你喜欢
    • 2011-12-26
    • 2016-04-27
    • 2014-04-13
    • 2020-11-10
    • 2017-05-13
    • 1970-01-01
    • 1970-01-01
    • 2013-02-24
    • 2015-04-22
    相关资源
    最近更新 更多