如何通过多个键对perl哈希进行排序?

Gre*_*reg 3 sorting perl hash

嗨,我有一个以下形式的数据结构:

$data = {                                                                                           
    'a' => { key1 => 2, key2 => 1 },                                                                   
    'b' => { key1 => 1, key2 => 2 },                                                                   
    'c' => { key1 => 1, key2 => 1 },                                                                   
    'd' => { key1 => 3, key2 => 2 },                                                                   
    'e' => { key1 => 3, key2 => 1 },                                                                   
    'f' => { key1 => 1, key2 => 2 },                                                                   
};
Run Code Online (Sandbox Code Playgroud)

我希望能够做的是按照哈希键的升序key2,降序key1,然后升序循环遍历此数据结构,例如:

e
a
c
d
b
f
Run Code Online (Sandbox Code Playgroud)

我怎样才能在perl中实现这一目标?我知道我可以使用键对哈希进行排序sort keys %$data,但是如何按多个值和键排序呢?

Hay*_*den 9

之前已经提出过一个类似的问题,可以在这里找到: 用多个键Perl对Hash数组进行排序

基本上,Perl有两个运算符用于排序,<=>cmp返回-1,0或1,具体取决于左侧是否小于,等于或大于右侧.<=>用于数字比较,cmp用于逐字比较.关于它们的使用的更多细节可以在这里找到:Equality Operators.

这些运算符可以与Perl的sort函数一起使用,并与or运算符结合使用,可以实现您之后的结果:

#!/usr/bin/perl

use strict;
use warnings;

my $data = {
    'a' => { key1 => 2, key2 => 1 },
    'b' => { key1 => 1, key2 => 2 },
    'c' => { key1 => 1, key2 => 1 },
    'd' => { key1 => 3, key2 => 2 },
    'e' => { key1 => 3, key2 => 1 },
    'f' => { key1 => 1, key2 => 2 },
};

my @sorted = sort {
        $data->{$a}->{key2} <=> $data->{$b}->{key2} or
        $data->{$b}->{key1} <=> $data->{$a}->{key1} or
        $a cmp $b
    } keys %{$data};

for my $key (@sorted){
    print "$key\n";
}
Run Code Online (Sandbox Code Playgroud)

由于<=>并且cmp返回0(false)表示相等,这意味着我们可以将等式检查与or或一起链接||.

在上面我们的例子中$a,并$b指代的一键$datahashref在某种特定的迭代.使用这些键,我们可以访问哈希的特定值,例如$data->{$a}->{key2}.通过$a$b它之前放置将导致排序按升序排列,并且放在$b之前$a将导致排序按降序排列.