Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Return all hash key/value pairs with maximum value

Tags:

hash

perl

I have a hash (in Perl) where the values are all numbers. I need to create another hash that contains all key/value pairs from the first hash where the value is the maximum of all values.

For example, given

my %hash = (
    key1 => 2,
    key2 => 6,
    key3 => 6,
);

I would like to create a new hash containing:

%hash_max = (
    key2 => 6,
    key3 => 6,
);

I'm sure there are many ways to do this, but am looking for an elegant solution (and an opportunity to learn!).

like image 357
itzy Avatar asked Apr 24 '26 19:04

itzy


2 Answers

use List::Util 'max';
my $max = max(values %hash);
my %hash_max = map { $hash{$_}==$max ? ($_, $max) : () } keys %hash;

Or a one-pass approach (similar to but slightly different from another answer):

my $max;
my %hash_max;
keys %hash; # reset iterator
while (my ($key, $value) = each %hash) {
    if ( !defined $max || $value > $max ) {
        %hash_max = ();
        $max = $value;
    }
    $hash_max{$key} = $value if $max == $value;
}
like image 69
ysth Avatar answered Apr 27 '26 08:04

ysth


This makes one pass over the data, but wastes a lot of hash writes:

use strict;
use warnings;

my %hash = (
    key1 => 2,
    key2 => 6,
    key3 => 6,
);

my %hash_max = ();
my $max;
foreach my $key (keys %hash) {
        if (!defined($max) || $max < $hash{$key} ) {
                %hash_max = ();
                $max = $hash{$key};
                $hash_max{$key} = $hash{$key};
        }
        elsif ($max == $hash{$key}) {
                $hash_max{$key} = $hash{$key};
        }
}

foreach my $key (keys %hash_max) {
        print "$key\t$hash_max{$key}\n";
}
like image 44
Mark Tozzi Avatar answered Apr 27 '26 07:04

Mark Tozzi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!