如何在Perl中按键对散列的散列进行排序?

balp4ylt  于 8个月前  发布在  Perl
关注(0)|答案(5)|浏览(81)

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

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

我在%hash2中插入了很多哈希值,并使用不同的%hash2计数值。
如何根据hash1的计数值对%hash1进行排序?
有没有一种方法可以做到这一点,而不需要手动实现快速排序,例如使用Perl的排序功能?

ix0qys7i

ix0qys7i1#

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

yqkkidmi2#

perlfaq4开始,我如何对散列排序(可选地按值而不是键)?的答案包含了将代码组合在一起所需的大部分信息。
您可能还想查看Learning Perl中的排序一章。
Chris有一个非常好的答案,尽管我讨厌这样使用values。一个更熟悉的方法是遍历顶层哈希的键,但按二级键排序:

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

我这样做是因为它少了一点脑筋急转弯。
如何对散列进行排序(可选按值而不是键)?
(brian d foy供稿)
要对散列进行排序,请从键开始。在本例中,我们给予键列表,然后排序函数将按ASCII顺序对它们进行比较(这可能会受到您的区域设置的影响)。输出列表中的键是按ASCII顺序排列的。一旦我们有了键,我们就可以遍历它们以创建一个按ASCII顺序列出键的报告。

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;
b4qexyjb

b4qexyjb3#

如果你想从hash2中的值中获得按计数排序的哈希列表(如hash1),这可能会有所帮助:

@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};
}
u0njafvf

u0njafvf4#

请参阅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";
fbcarpbf

fbcarpbf5#

按数值排序使用<=>,字符串排序使用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";
}

相关问题