【问题标题】:Sorting alphanumeric hash keys in Perl?在Perl中对字母数字哈希键进行排序?
【发布时间】:2016-08-29 19:42:20
【问题描述】:

给定以下哈希:

%errors = (
    "2013-W9 -> 2013-W12" => 1,
    "2013-W5 -> 2013-W8" => 1,
    "2013-W13 -> 2013-W15" => 1
)

我正在尝试像这样对其进行排序(这样我就可以在foreach 循环中使用它):

%errors = (
    "2013-W5 -> 2013-W8" => 1,
    "2013-W9 -> 2013-W12" => 1,
    "2013-W13 -> 2013-W15" => 1
)

我试过sort keys %errorssort{$a <=> $b) keys %errors 都没有成功。

我该如何解决这个问题?

【问题讨论】:

  • 您会在这些键中看到其他字母吗?比如2013-X12?
  • 当您调用排序键 %errors 时,它是如何对哈希进行排序的?
  • 是的,我可能还会看到其他字母,例如 M 代表月份。顺便说一句,W 是一周。

标签: perl sorting


【解决方案1】:

似乎在这种情况下,CPAN 模块 Sort::Naturally 工作正常:

use Sort::Naturally qw(nsort);
say $_ for nsort keys %errors;

【讨论】:

    【解决方案2】:

    目前尚不完全清楚您想要什么排序顺序,但这种方法可以轻松扩展:

    #!/usr/bin/perl
    
    use strict;
    use warnings;
    use 5.010;
    
    my %errors = (
        "2013-W9 -> 2013-W12" => 1,
        "2013-W5 -> 2013-W8" => 1,
        "2013-W13 -> 2013-W15" => 1
    );
    
    my @sorted_keys = map { $_->[0] }
      sort { $a->[1] <=> $b->[1] }
      map  { [ $_, /W(\d+)/ ] } keys %errors;
    
    say $_ for @sorted_keys;
    

    【讨论】:

      【解决方案3】:

      The Alphanum Algorithm 有一个通用的字符串排序例程,将数字子字符串作为数字进行比较,在包括 Perl 在内的许多语言中实现。

      【讨论】:

        【解决方案4】:

        键将按升序排列yyyy-Wx;首先比较yyyy,然后比较x数字,

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

        【讨论】:

        • 也许我需要更多的咖啡……那不正确吗? 9 小于 13。但另一方面,它可能会弄乱后续编号,例如嗯...2013-1 -&gt; 2013-99 vs 2013-10 -&gt; 2013-1
        • 我想正确的方法是在这种情况下用零填充数字,这样9 -> 09。然后你必须知道最大长度有多长,并且你必须确保不超过最大整数大小(如果字符串很长)。也许你原来的方式毕竟是更简单的选择。
        【解决方案5】:

        我也遇到过类似的情况。我通过以下方式解决了我的问题:

        你试过了

        sort keys %errors
        

        sort{$a <=> $b) keys %errors
        

        只需尝试几乎类似的东西,但有一点不同:

        代码:

        my %errors = (
            "2013-W9 -> 2013-W12" => 1,
            "2013-W5 -> 2013-W8" => 1,
            "2013-W13 -> 2013-W15" => 1);
        
        foreach my $val(sort {my ($anum) = ($a =~ /\d+-\w(\d+)$/);  my ($bnum) = ($b =~ /\d+-\w(\d+)$/);  $anum <=> $bnum} keys %error
        {
            print "$val\n";
        }
        

        在上面的例子中,我只打印了键。

        输出:

        2013-W5 -> 2013-W8
        2013-W9 -> 2013-W12
        2013-W13 -> 2013-W15
        

        【讨论】:

          猜你喜欢
          • 2014-04-13
          • 2011-12-26
          • 2016-04-27
          • 2021-12-07
          • 1970-01-01
          • 2013-05-19
          • 2014-08-03
          • 2013-06-06
          • 2012-01-21
          相关资源
          最近更新 更多