Perl 按值对哈希进行排序

Perl Sorting Hash by Value of Value

我有一个看起来像

的散列

'Jarrod' => {
                                'Age' => '25 ',
                                'Occupation' => Student
                              },
'Elizabeth' => {
                                'Age' => '18',
                                'Occupation' => Student
                                },
'Nick' => {
                                'Age' => '32 ',
                                'Occupation' => Lawyer
                               },

我正在尝试按年龄对它们进行排序,这样它看起来像

'Nick' => {
                                'Age' => '32 ',
                                'Occupation' => Lawyer
                               },
'Jarrod' => {
                                'Age' => '25 ',
                                'Occupation' => Student
                              },
'Elizabeth' => {
                                'Age' => '18',
                                'Occupation' => Student
                                },

但我似乎无法弄清楚如何访问超过 Age 的任何内容。订购哈希键时如何访问值的值?

具有所示数据的散列变量 %h 可以按照所需的顺序进行处理,如

use Data::Dump qw(pp);  # to print out a complex data structure

say "$_->[0] => ", pp($_) for 
    map { [ $_, $h{$_} ] } 
        sort { $h{$b}->{Age} <=> $h{$a}->{Age} } 
             keys %h;

打印什么(来自下面的完整程序)

Nick => { Age => "32 ", Occupation => "Lawyer" }
Jarrod => { Age => "25 ", Occupation => "Student" }
Elizabeth => { Age => 18, Occupation => "Student" }

请注意,我们不能对散列进行“排序”,然后就这样,因为散列本质上是随机的。但是我们当然可以通过并按特定顺序处理元素,例如上面的示例。

解释:sort takes pairs of elements of a submitted list in turn, available in variables $a and $b, and then runs the block of code we provide, so to compare他们按照规定。在这里,我们根据键 Age.

处的值比较并排序元素

不过,输出只是这样排序的那些键!所以我们然后通过 map 传递它,它将每个键与其 hashref 值和 returns 这些对组合在一起,每个都在一个 arrayref 中。那是用来打印它们的,作为实际处理的占位符。

一个完整的程序

use warnings;
use strict;
use feature 'say';
use Data::Dump qw(dd pp);

my %h = ( 
    'Jarrod' => {
        'Age' => '25 ',
        'Occupation' => 'Student'
    },  
    'Elizabeth' => {
        'Age' => '18',
        'Occupation' => 'Student'
    },  
    'Nick' => {
        'Age' => '32 ',
        'Occupation' => 'Lawyer'
    },  
);

say "$_->[0] => ", pp($_->[1]) for 
    map { [ $_, $h{$_} ] } sort { $h{$b}->{Age} <=> $h{$a}->{Age} } keys %h; 

或者,对于可行的模板,更改为

my @sorted_pairs = 
    map { [ $_, $h{$_} ] } sort { $h{$b}->{Age} <=> $h{$a}->{Age} } keys %h;

for my $key_data (@sorted_pairs) {
    say $key_data->[0], ' => ', pp $key_data->[1];  # or just: dd $key_data;

    # my ($name, $data) = @$key_data;
    # Process $data (a hashref) for each $name
}

一旦我们开始为有序数据构建更合适的数据结构,就会有多种选择,包括每个名称的 one-person hashrefs,以正确的顺序存储在数组中。最终,所有这些都可以很好地组织在 class.


请注意 Sort::Key 如何使排序部分变得不那么麻烦

use Sort::Key qw(rnkeysort);  # rn... -> Reverse Numerical

my @pairs = map { [ $_, $h{$_} ] } rnkeysort { $h{$_}->{Age} } keys %h;

排序越复杂(或特定),此模块的好处就越大,它有许多针对通用标准的特定功能。

如果这些年龄以整数形式给出,则有 ikeysort(和 rikeysort),然后这些是无符号整数,因此有 ukeysort(和 rukeysort).


例如参见 [​​=26=]。

您无法对哈希进行排序。哈希的元素本质上是无序的。


如果你只想按顺序访问散列的元素,你可以通过获取和排序键来实现。

for my $name (
   sort { $people{ $b }{ age } <=> $people{ $a }{ age } }
      keys( %people ) 
) {
   my $person = $people{ $name };
   ...
}

use Sort::Key qw( rikeysort );

for my $name (
   rikeysort { $people{ $_ }{ age } }
      keys( %people ) 
) {
   my $person = $people{ $name };
   ...
}

如果您需要一个有序的结构,您可以先将数据转换为一组人。

my @unordered_people =
   map { +{ name => $_, %{ $people{ $_ } } }
      keys( %people );

然后排序。

my @ordered_people =
   sort { $b->{ age } <=> $a->{ age } }
      @unordered_people;

use Sort::Key qw( rikeysort );

my @ordered_people =
   rikeysort { $_->{ age } }
      @unordered_people;