How do I sort(and print) a multi-level perl hash based on key value ?
%hash = (
a => { k1 => 51, k2 => 52, k3 => 53 },
b => { k1 => 61, k2 => 62, k3 => 63 },
c => { k1 => 71, k2 => 72, k3 => 73 },
)
For example sort the above hash numerically based on the value of k2?
So it should print:
52,62,72
I wanted to know how I can expand sorting single level hashes to multilevel using
sort { $hash{$b} <=> $hash{$a} } keys %hash`
Edit
If I have another hash
my %property = ( a => 7, b => 6, c => 5 )
Can I sort %hash based on numerical value of $hash{key}{k2} * $property{key}
using
#!/usr/bin/perl
use strict;
use warnings;
my %hash = (
a => { k1 => 51, k2 => 52, k3 => 53 },
b => { k1 => 61, k2 => 62, k3 => 63 },
c => { k1 => 71, k2 => 72, k3 => 73 },
);
my %property = ( a => 7, b => 6, c => 5 );
foreach (sort { ($hash{$a}{'k2'}*$property{$a}) <=>
($hash{$b}{'k2'}*$property{$b}) } keys %hash)
{
printf("[%d][%d][%d]\n",
$hash{$_}{'k2'},$property{$_},$hash{$_}{'k2'}*$property{$_});
}
result should be
72,52,62 as products are (360(72*5),364(52*7),372(62*6))
Get a list of all values in the hash:
values %hash;
transform a list of hashrefs to the contents of the k2 entry:
map $_->{k2}, @list
oh, skip it if it's undef/doesn't exist:
map $_->{k2} // (), @list
sort a list numerically:
sort { $a <=> $b } @list
connect the dots:
sort { $a <=> $b } map { $_->{k2} // () } values %hash;
sort {$hash{$a}{'k2'} <=> $hash{$b}{'k2'}} keys %hash
The spaceship operator numerically compares the left-hand side with the right-hand side. It's most often seen in its simplest case, with
$a <=> $b
but in this case, you want to compare values from a hash and it can do that too.
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