I want to sort a hash which actually has a hash as a value. For instance:
my %hash1=(
field1=>"",
field2=>"",
count=>0,
);
my %hash2;
$hash2{"asd"}={%hash1};
and I inserted lots of hashes to %hash2
with different count values of %hash2
.
How can I sort the %hash1
according to a count value of hash1
?
Is there a way of doing this without implementing quicksort manually, for instance with the sort function of Perl?
my @hash1s = sort {$a->{count} <=> $b->{count}} values %hash2;
From perlfaq4, the answer to "http://faq.perl.org/perlfaq4.html#How_do_I_sort_a_hash" has most of the information you need to put together your code.
You might also want to see the chapter on Sorting in Learning Perl.
Chris has a completely fine answer, although I hate using values
like that. A more familiar way to do the same thing is to go through the keys of the top-level hash but sort by the second-level key:
my @sorted_hashes =
sort { $hash2->{$a}{count} <=> $hash2->{$b}{count} }
keys %hash2;
I do it this way because it's a little less mind-bending.
How do I sort a hash (optionally by value instead of key)?
(contributed by brian d foy)
To sort a hash, start with the keys. In this example, we give the list of keys to the sort function which then compares them ASCIIbetically (which might be affected by your locale settings). The output list has the keys in ASCIIbetical order. Once we have the keys, we can go through them to create a report which lists the keys in ASCIIbetical order.
my @keys = sort { $a cmp $b } keys %hash;
foreach my $key ( @keys )
{
printf "%-20s %6d\n", $key, $hash{$key};
}
We could get more fancy in the sort() block though. Instead of comparing the keys, we can compute a value with them and use that value as the comparison.
For instance, to make our report order case-insensitive, we use the \L sequence in a double-quoted string to make everything lowercase. The sort() block then compares the lowercased values to determine in which order to put the keys.
my @keys = sort { "\L$a" cmp "\L$b" } keys %hash;
Note: if the computation is expensive or the hash has many elements, you may want to look at the Schwartzian Transform to cache the computation results.
If we want to sort by the hash value instead, we use the hash key to look it up. We still get out a list of keys, but this time they are ordered by their value.
my @keys = sort { $hash{$a} <=> $hash{$b} } keys %hash;
From there we can get more complex. If the hash values are the same, we can provide a secondary sort on the hash key.
my @keys = sort {
$hash{$a} <=> $hash{$b}
or
"\L$a" cmp "\L$b"
} keys %hash;
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