如何在Perl中按键对散列哈希值进行排序?

时间:2009-04-13 06:20:40

标签: perl sorting hash

我想对实际上有哈希作为值的哈希进行排序。例如:

my %hash1=(
   field1=>"",
   field2=>"",
   count=>0,
);
my %hash2;
$hash2{"asd"}={%hash1};

我向%hash2插入了大量哈希值,其中%hash2的计数值不同。

如何根据%hash1的计数值对hash1进行排序?

有没有办法在不手动实现快速排序的情况下执行此操作,例如使用Perl的sort函数?

5 个答案:

答案 0 :(得分:10)

my @hash1s = sort {$a->{count} <=> $b->{count}} values %hash2;

答案 1 :(得分:6)

perlfaq4开始,"http://faq.perl.org/perlfaq4.html#How_do_I_sort_a_hash"的答案包含了汇总代码所需的大部分信息。

您可能还希望在学习Perl 中看到有关排序的章节。

克里斯有一个完全正确的答案,尽管我讨厌像这样使用values。执行相同操作的更熟悉的方法是遍历顶级哈希的键,但按二级键排序:

my @sorted_hashes = 
    sort { $hash2->{$a}{count} <=> $hash2->{$b}{count} } 
    keys %hash2;

我是这样做的,因为它不那么令人费解。


如何对哈希进行排序(可选择按值而不是键)?

(由brian d foy提供)

要对哈希进行排序,请从键开始。在这个例子中,我们给sort函数提供了一个键列表,然后用ASCII比较它们(这可能会受到你的语言环境设置的影响)。输出列表具有ASCIIbetical顺序的键。获得密钥后,我们可以通过它们创建一个报告,按ASCIIbetical顺序列出密钥。

my @keys = sort { $a cmp $b } keys %hash;

foreach my $key ( @keys )
    {
    printf "%-20s %6d\n", $key, $hash{$key};
    }

虽然我们可以在sort()块中获得更多的幻想。我们可以使用它们计算一个值,并使用该值作为比较,而不是比较键。

例如,为了使我们的报表顺序不区分大小写,我们在双引号字符串中使用\ L序列使所有内容都小写。然后sort()块比较小写值以确定放置键的顺序。

my @keys = sort { "\L$a" cmp "\L$b" } keys %hash;

注意:如果计算成本很高或哈希有很多元素,您可能需要查看Schwartzian变换来缓存计算结果。

如果我们想要通过哈希值进行排序,我们使用哈希键来查找它。我们仍然会得到一个密钥列表,但这次它们按其值排序。

my @keys = sort { $hash{$a} <=> $hash{$b} } keys %hash;

从那里我们可以变得更复杂。如果哈希值相同,我们可以在哈希键上提供辅助排序。

my @keys = sort {
    $hash{$a} <=> $hash{$b}
        or
    "\L$a" cmp "\L$b"
    } keys %hash;

答案 2 :(得分:1)

如果你想得到散列的列表(比如hash1),这些列表是按照hash2中的值计算的,这可能会有所帮助:

@sorted_hash1_list = sort sort_hash_by_count_key($a, $b) (values (%hash2);


# This method can have any logic you want
sub sort_hash_by_count_key {
    my ($a, $b) = @_;
    return $a->{count} <=> $b->{count};
}

答案 3 :(得分:0)

请参阅http://perldoc.perl.org/functions/sort.html了解有关Perl中排序的工作原理。

这是一个例子..试图可读,而不是perlish。

#!/usr/bin/perl
# Sort Hash of Hashes by sub-hash's element count.
use warnings;
use strict;


my $hash= {
            A=>{C=>"D",0=>"r",T=>"q"}
           ,B=>{}
           ,C=>{E=>"F",G=>"H"}
          };

sub compareHashKeys {0+(keys %{$hash->{$a}}) <=> 0+(keys %{$hash->{$b}}) }

my @SortedKeys = sort compareHashKeys keys %{$hash};
print join ("," , @SortedKeys) ."\n";

答案 4 :(得分:0)

按数字排序&lt; =&gt;和字符串使用cmp。

# sort by the numeric count field on inner hash
#
foreach my $key (sort {$hash2{$a}->{'count'} <=> $hash2{$b}->{'count'}} keys %hash2) {
   print $key,$hash2{$key}->{'count'},"\n";
}

# sort by the string field1 (or field2) on the inner hash
#
foreach my $key (sort {$hash2{$a}->{'field1'} cmp $hash2{$b}->{'field1'}} keys %hash2) {
   print $key,$hash2{$key}->{'field1'},"\n";
}

要反转订单,只需交换$ a和$ b:

# sort by the numeric count field on inner hash
#
foreach my $key (sort {$hash2{$a}->{'count'} <=> $hash2{$b}->{'count'}} keys %hash2) {
   print $key,$hash2{$key}->{'count'},"\n";
}

# sort by the string field1 (or field2) on the inner hash
#
foreach my $key (sort {$hash2{$a}->{'field1'} cmp $hash2{$b}->{'field1'}} keys %hash2) {
   print $key,$hash2{$key}->{'field1'},"\n";
}