Hi I have a data structure which is of the following form:
$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 },
};
what I want to be able to do is loop through this data structure in ascending order of key2
, descending order of key1
, and then ascending order of the hash key, e.g:
e
a
c
d
b
f
how can I achieve this in perl? I know that I can sort the hash by key using sort keys %$data
, but how can I sort by multiple values and keys?
A similar question has been asked before and can be found here: Sorting an Array of Hash by multiple keys Perl
Basically, Perl has two operators for sorting, <=>
and cmp
which return -1, 0 or 1, depending on if the left hand side is less than, equal to, or greater than the right hand side. <=>
is used for numerical comparison, and cmp
is used for stringwise comparison. More detail about their use can be found here: Equality Operators.
These operators can be used with Perl's sort
function and in conjuction with the or
operator can be used to achieve the result you're after:
#!/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";
}
Since <=>
and cmp
return 0 (false) for equality, it means we can chain equality checks together with or
or ||
.
In the example above we $a
and $b
to refer to a key of the $data
hashref at a particular iteration of the sort. Using these keys we can access particular values of the hash, e.g. $data->{$a}->{key2}
. By putting $a
before $b
it will cause the sort to be in ascending order, and putting $b
before $a
will cause the sort to be in descending order.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With