accessing the highest value in hash of an hash in perl?
-
21-12-2019 - |
Question
so i have a hash of an hash that looks something like this:
my %hash = (
'fruits' => {
'apple' => 34,
'orange' => 30,
'pear' => 45,
},
'chocolates' => {
'snickers' => 35,
'lindt' => 20,
'mars' => 15,
},
);
I want to access only the fruit which is max in number and chocolate which is max in number. the output should look like:
fruits: pear chocolates : snickers
foreach my $item (keys %hash){
#print "$item:\t"; # this is the object name
foreach my $iteminitem (keys %{$hash{$item}})
{
my $longestvalue = (sort {$a<=>$b} values %{$hash{$item}})[-1]; #this stores the longest value
print "the chocolate/fruit corresponding to the longestvalue" ;
#iteminitem will be chocolate/fruit name
}
print "\n";
}
I know it is not difficult but I am blanking out!
Solution
The following sorts the keys of each hashref by descending value, so the max is the first element returned:
my %hash = (
chocolates => { lindt => 20, mars => 15, snickers => 35 },
fruits => { apple => 34, orange => 30, pear => 45 },
);
while (my ($key, $hashref) = each %hash) {
my ($max) = sort {$hashref->{$b} <=> $hashref->{$a}} keys %$hashref;
print "$key: $max\n";
}
Outputs:
fruits: pear
chocolates: snickers
OTHER TIPS
Here is another way:
use strict;
use warnings;
use List::Util qw(max);
my %hash = (
'fruits' => {
'apple' => 34,
'orange' => 30,
'pear' => 45,
},
"chocolates" => {
'snickers' => 35,
'lindt' => 20,
'mars' => 15,
},
);
for (keys %hash) {
my $max = max values %{$hash{$_}}; # Find the max value
my %rev = reverse %{$hash{$_}}; # Reverse the internal hash
print "$_: $rev{$max}\n"; # Print first key and lookup by max value
}
Output:
fruits: pear
chocolates: snickers
For this you likely want List::UtilsBy
:
use List::UtilsBy 'max_by';
my %hash = (
chocolates => { lindt => 20, mars => 15, snickers => 35 },
fruits => { apple => 34, orange => 30, pear => 45 },
);
foreach my $key ( keys %hash ) {
my $subhash = $hash{$key};
my $maximal = max_by { $subhash->{$_} } keys %$subhash;
print "$key: $maximal\n";
}
For this small example it probably doesn't matter too much, but for much larger cases, there's a big difference. This will run in O(n)
time for the size of the hash, whereas the "sort and take first index" solution will take O(n log n)
time, much slower, to sort the list of keys, only to then throw away all but the first result.