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!

Was it helpful?

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top