http://qs1969.pair.com?node_id=1026317

maciej has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I've recently been learning a bit of perl and this site has been super helpful, so thanks to everyone who contributes.

Anyway, I've come across a problem I cannot seem to be able to figure out. I'm trying to find the coresponding key for the highest value of a hash.

My attempt is:

```#!/usr/bin/perl
use warnings;
use strict;

my %hash=  ( '1', '8', '2', '6', '3','3' ,'4','7');
my \$highest =0;
while (my (\$key, \$value) = each %hash) {
\$highest=\$key if (\$highest <  \$value) ;
print "\$key key has a value \$value \n";
}
print "\$highest key has the highest value\n";

and my results look like:

```4 key has a value 7
1 key has a value 8
3 key has a value 3
2 key has a value 6
2 key has the highest value

Where as I am trying to get the last line to say "1 key has the highest value" since the value of "1" is "8"... Both keys 1 and 4 have a higher value than 2.

any tips are much appreciated.

Replies are listed 'Best First'.
Re: highest value in hash
by LanX (Sage) on Mar 31, 2013 at 03:35 UTC
a maximal value can belong to more than just one key!

```  DB<140> %h = map {\$_ => int rand 3} "a" .."f"
=> ("a", 1, "b", 0, "c", 2, "d", 2, "e", 2, "f", 0)

DB<141> use List::Util qw/max/

DB<142> \$max = max values %h
=> 2

DB<143> @max_keys = grep { \$h{\$_} == \$max } keys %h
=> ("e", "d", "c")

Cheers Rolf

( addicted to the Perl Programming Language)

Re: highest value in hash (key is not value)
by Anonymous Monk on Mar 31, 2013 at 02:27 UTC

You have   \$highest=\$key if (\$highest <  \$value) ;

You're storing the key, and comparing the key to the value

But it sounds like you want to compare values, not keys

So you need to store \$highest_key and \$highest_value, and compare \$highest_value to \$value

Wow, I was trying to figure that out for the longest time and now that you pointed out what I was doing it's so obviouse. duh! Thanks everyone!

Wow, I was trying to figure that out for the longest time and now that you pointed out what I was doing it's so obviouse. duh! Thanks everyone!

No problemo :)

I used the virtual teddybear method

Basically, I read your program aloud , in my head (virtual), until i said "highest becomes key if highest lessthan value"

Actually I said "highest is" but "becomes" sounds better -- I'm not very disciplined when it comes to speaking code

Also known as teddy bear debugging , mirror debugging, empty room debugging, talking to yourself, Rubber Duck method of debugging, say it out loud George, sing into that hairbrush ...

Re: highest value in hash
by Athanasius (Archbishop) on Mar 31, 2013 at 02:44 UTC

Hello maciej, and welcome to the Monastery!

Expanding on the advice from Anonymous Monk, here is one way to implement the solution:

```#! perl
use warnings;
use strict;

my %hash = (1 => 8, 2 => 6, 3 => 3, 4 => 7);
my \$highest_value;
my \$highest_key;

while (my (\$key, \$value) = each %hash)
{
print "\$key key has value \$value\n";

if (!defined \$highest_value || \$highest_value < \$value)
{
\$highest_key   = \$key;
\$highest_value = \$value;
}
}

print "The element with key \$highest_key " .
"has the highest value \$highest_value\n" if defined \$highest_key
+;

Output:

```12:36 >perl 591_SoPW.pl
4 key has value 7
1 key has value 8
3 key has value 3
2 key has value 6
The element with key 1 has the highest value 8

12:38 >

Note that this uses < to compare values numerically. To compare the values as strings, you would need to use lt instead:

```if (!defined \$highest_value || \$highest_value lt \$value)

Hope that helps,

Update: ++Anonymous Monk for the syntax below: it’s both simpler and more efficient. Confession: I had to re-read the documentation for each to verify that it Does the Right Thing here (it does). :-)

 Athanasius <°(((>< contra mundum Iustus alius egestas vitae, eros Piratica,

Just say no to defined :)
```...
my( \$highest_value, \$highest_key  ) = each %hash;
while (my (\$key, \$value) = each %hash)
...
Re: highest value in hash
by hdb (Monsignor) on Apr 01, 2013 at 08:55 UTC

Should performance be not your highest goal, you can sort the keys of the hash by their values in descending order and pick the first one:

```use warnings;
use strict;

my %hash=  ( '1', '8', '2', '6', '3','3' ,'4','7');
my @keys = sort { \$hash{\$b} <=> \$hash{\$a} } keys %hash;
print "Key with highest value is \$keys[0].\n";
Re: highest value in hash
by nvivek (Vicar) on Apr 01, 2013 at 06:12 UTC

Need to maintain both key and value in code to find which key has a largest value among all the key pairs in hash. Following is a one more way to achieve your requirement.

```use strict;
use warnings;
use Data::Dumper;
# initializing hash
%hash=  ( '1' => '8',
'2' => '6',
'3' => '3',
'4' => '7');
# print the structure
print Dumper \%hash;
# maintaining key and value of highest value in hash
# 0th index => Key
# 1st index => Value
my @larger =(0,0);
while (my (\$key, \$value) = each %hash) {
# compares value with each value of hash
# stores key and value whenever current value is greater than prev
+ious value
@larger=(\$key, \$value) if (\$larger[1] <  \$value) ;
print "\$key key has a value \$value \n";
}
# finally prints the key which has larger value
+
print \$larger[0]. " key has the larger value\n";