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