【问题标题】:Alphanumeric or natural sorting of keys in a hash [duplicate]哈希中键的字母数字或自然排序[重复]
【发布时间】:2016-01-26 19:34:02
【问题描述】:

我在哈希中有如下键:AB3, AB1, AB2 等等。我想按键对哈希进行排序。我如何在 perl 中做到这一点?

一个相关的问题是如何对键进行排序以使字母和数字以正确的顺序出现?

【问题讨论】:

标签: perl sorting data-structures hash perl-data-structures


【解决方案1】:

你需要sort函数:

foreach my $key ( sort keys %hash ) {
    print "$key => $hash{$key}\n"; 
}

您不能轻松地将散列维护为排序结构,因为它们不能那样工作。有关哈希如何工作的更多信息,请参阅:perldata。

编辑:sort 在 perl 中的优点之一是它允许您指定一个函数。此函数应采用 $a 和 $b 并返回 -1、0、+1,具体取决于它们是之前还是之后。

cmp 按字母顺序执行此操作。 <=> 以数字方式执行此操作。最重要的是,当与|| 结合使用时,您可以菊花链标准,因为-1 或1 是“真”但0 是假的。

例如这样的事情(借用另一个帖子的关键列表来说明):

#!/usr/bin/env perl
use strict;
use warnings;

use Data::Dumper;

my @keys = qw/ AB3 AB1 AB4
    CD5 CD107 CB8
    AC1 AC5 AC33
    BA84 CB11 CA233/;


sub lex_num {
    #split the keys into "word" and "digit" elements. 
    my @a_keys = $a =~ m/([A-Z]+)(\d+)/i;
    my @b_keys = $b =~ m/([A-Z]+)(\d+)/i;

    return ( $a_keys[0] cmp $b_keys[0] 
          || $a_keys[1] <=> $b_keys[1] );
}

print join( "\n", sort lex_num @keys );

这将按词法排序第一位,按数字排序第二位。如果您有更多字母和数字的组合,那么这将不起作用,但您可以这样做,例如split 和 for 循环。

【讨论】:

  • 你的答案是规范的:-)(最接近常见问题解答中的答案)我尝试将基础知识与@Toto 使用模块提出的排序顺序问题结合起来。 Sobrique 和 Toto:是否有更短的“成语”可以进行自然排序,或者使用可防御的模块,直到人们理解 Toto 响应中的代码?
  • 自然排序是什么意思?如果我有一个双键类型排序(如数字/字母),那么通常我会做一个正则表达式来捕获两个不同的值。
  • 好吧,或多或少像@Toto 所做的那样?当我读到它时,Sort::Naturally 或多或少隐藏了您可以传递给模块内的sort() 函数的块,并提供了一个方便的函数来很好地包装。
  • 差不多。使用较长的键列表添加了我自己的插图。
  • 模块通常是有益的,但我发现它确实有助于理解幕后实际发生的事情 - 我假设 Sort::Naturally 做的事情比上面的更全面,但这已经足够了给定样本数据。
【解决方案2】:

如果您的键是由非数字后跟数字定义的,您可以这样做:

my %h = (
  CD45 => 4,
  AB1 => 1,
  AB22 => 3,
  AB5 => 2,
);
sub mySort {
  my ($xa,$ya) = $a =~ /^(\D+)(\d+)$/;
  my ($xb,$yb) = $b =~ /^(\D+)(\d+)$/;
  return -1 if $xa lt $xb;
  return +1 if $xa gt $xb;
  return $ya <=> $yb;
}
for (sort { mySort } keys %h) {
  say "$_ => $h{$_}";
}

输出:

AB1 => 1
AB5 => 2
AB22 => 3
CD45 => 4

【讨论】:

  • 很好地回答了通常是排序操作的困难部分。不幸的是,我们不得不猜测原始发布者试图解决什么问题。
【解决方案3】:

您可以通过以下方式结合这两种方法并使用 CPAN 模块缩短代码 - 在本例中为 Sort::Naturally(出于说明目的,我将哈希键变得更复杂):

use Sort::Naturally ;

my @keys = qw/ AB3 AB1 AB4 
               CD5 CD107 CB8 
               AC1 AC5 AC33 
               BA84 CB11 CA233/ ;

# make a hash from the keys with "whatever" as value:
my %hash;
%hash = map { $_ => $hash{$_} = 'whatever' } @keys ; 

# Auto-magically naturally sort alphanumerically
# A module based approach to @Toto's solution:
for ( nsort keys %hash ) { print "$_ => $hash{$_} \n" };

@Sobrique 已经响应了基本的 perl 方法来按其键对散列进行排序,@Toto 已经展示了如何使用您自己的子例程作为块 { } 中的参数以指定的顺序对这些键进行排序遵循内置的sort() 函数。

参考文献:

【讨论】:

  • 删除散列片 5.20-ism: $_ = "whatever" for %hash{@keys};
猜你喜欢
  • 2011-12-26
  • 2014-04-13
  • 1970-01-01
  • 2018-02-19
  • 2016-04-27
  • 1970-01-01
  • 2013-05-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多