Perl:按值降序对哈希散列进行排序

时间:2014-03-27 21:48:24

标签: perl sorting hash

数据:

%HoH => (
 abc => {
           value    => "12",
 },
 xyz => {
           number    => "100",
 },
 pqr => {
           digit    => "5",
 }
)

如何按降序对哈希值进行排序? 输出

100
12
5

3 个答案:

答案 0 :(得分:1)

您无法对哈希进行排序,它不会保留order。如果您想对它们进行排序,则必须根据数字对键进行排序,并将键存储在数组中

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

my %HoH = (
                abc => { value => 12 },
                xyz => { value => 100},
                pqr => { value => 5},
                def => { value => 15},
                hij => { value => 30},
          );

my @sorted_keys = map  { $_->[0] }
          sort { $b->[1] <=> $a->[1] } # use numeric comparison
          map  { my $temp;
                if ( exists $HoH{$_}{'value'} ) {
                        $temp = $HoH{$_}{'value'};
                } elsif ( exists $HoH{$_}{'number'} ) {
                        $temp = $HoH{$_}{'number'};
                } elsif ( exists $HoH{$_}{'digit'} ) {
                        $temp = $HoH{$_}{'digit'};
                } else {
                        $temp = 0;
                }
                {[$_, $temp]} }
               (keys %HoH);

for my $key (@sorted_keys) {
        my $temp;
        if ( exists $HoH{$key}{'value'} ) {
                $temp = $HoH{$key}{'value'};
        } elsif ( exists $HoH{$key}{'number'} ) {
                $temp = $HoH{$key}{'number'};
        } elsif ( exists $HoH{$key}{'digit'} ) {
                $temp = $HoH{$key}{'digit'};
        } else {
                $temp = 0;
        }
        print $key . ":" . $temp ."\n";
}

输出:

xyz:100
hij:30
def:15
abc:12
pqr:5

这种进行排序的技术称为Schwartzian Transform

答案 1 :(得分:0)

我提出了这个解决方案

#!/usr/bin/perl

use strict;
use warnings;

my %HoH = (
     abc => {
               value    => "12",
     },
     xyz => {
               number    => "100",
     },
     pqr => {
               digit    => "5",
     }
    );

my %rever;  
for my $TopKey(keys %HoH){
    for my $value(values %{ $HoH{$TopKey} }){
        push @{ $rever{$value} }, $TopKey;
    }
}

my @nums = sort {$b <=> $a} (keys(%rever));

print $_, "\n" for @nums;

如果您仍需要使用密钥名称,我会反转这些值。

这是使用Dumper的原因。

$VAR1 = '100';
$VAR2 = [
          'xyz'
        ];
$VAR3 = '12';
$VAR4 = [
          'abc'
        ];
$VAR5 = '5';
$VAR6 = [
          'pqr'
        ];

答案 2 :(得分:0)

鉴于您实际上没有使用任何键,您可以将数据结构展平为单个数组,然后对其进行排序:

use strict;
use warnings;

my %HoH = (
    abc => {value    => "12",},
    xyz => {number    => "100",},
    pqr => {digit    => "5",},
);

my @numbers = sort {$b <=> $a} map {values %$_} values %HoH;

print "$_\n" for @numbers;

输出:

100
12
5

但是,如果您想使用其他密钥信息,那么您需要将Hash of Hash折叠成一个数组,然后您可以按照自己的喜好排序:

my @array;
while (my ($k, $ref) = each %HoH) {
    while (my ($k2, $v) = each %$ref) {
        push @array, [$k, $k2, $v];
    }
}

@array = sort {$b->[2] <=> $a->[2]} @array;

use Data::Dump;
dd \@array;

输出:

[
  ["xyz", "number", 100],
  ["abc", "value", 12],
  ["pqr", "digit", 5],
]