laziness, impatience, and hubris PerlMonks

### How to get 2nd highest value from an array?

by rsiedl (Friar)
 on Dec 13, 2005 at 22:29 UTC Need Help??

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

Hey Monks!

Can anyone tell me if there is an easy way, module or method, to get the second highest value from an array?

I know List::Util will do the highest...

Update: Oops, i actually meant to say: Is there anyway to do this same thing on the values of a hash?

Cheers,
Reagen

Replies are listed 'Best First'.
Re: How to get 2nd highest value from an array?
by jeffa (Bishop) on Dec 13, 2005 at 22:57 UTC

Update: Oops, i actually meant to say: Is there anyway to do this same thing on the values of a hash?

Do you mean just the values themselves or the keys based on the values? Here is some code for both cases:

```my %hash = (
4 => 20,    # second highest key
2 => 40,    # second highest value
3 => 30,
1 => 50,
5 => 10,
);

# second highest value
print ((sort values %hash)[-2]);

# key based on the second highest value
print ((sort { \$hash{\$b} <=> \$hash{\$a} } keys %hash)[1]);
For the second example, since we already have to specify a sort block, i choose to sort descending and use the subscript 1 and not -2. TIMTOWTDI. :)

jeffa

```L-LL-L--L-LL-L--L-LL-L--
-R--R-RR-R--R-RR-R--R-RR
B--B--B--B--B--B--B--B--
H---H---H---H---H---H---
```
Re: How to get 2nd highest value from an array?
by GrandFather (Saint) on Dec 13, 2005 at 22:37 UTC
```use warnings;
use strict;

my @list = (4, 7, 1, 3, 2, 9);
my \$second = (sort @list)[-2];
print \$second;

Prints:

```7

DWIM is Perl's answer to Gödel

Of course if @list has only one element you may get an unexpected result . . . :)

Re: How to get 2nd highest value from an array?
by davidrw (Prior) on Dec 13, 2005 at 22:37 UTC
doesn't take into account short (or string/custom sorts) lists, but as a starting point:
```my @arr = qw/ 1 9 8 7 6 2 3 4 5/;
print ( (sort @arr)[-2] );
Re: How to get 2nd highest value from an array?
by gjb (Vicar) on Dec 13, 2005 at 23:12 UTC

If the list (or hash) is large, first doing a sort is a Really Bad IdeaTM given that this is an O(n log n) operation. As choedebeck's code above illustates it can be done in time linear in the size of the list/hash, i.e., O(n). This is a significant difference for large values of n.

Hope this helps, -gjb-

Re: How to get 2nd highest value from an array?
by choedebeck (Beadle) on Dec 13, 2005 at 22:59 UTC
This was actually an interview question I had for my first job, only I had to do it in C. Here is a solution without a sort.
```sub getSecondLargest
{
my (@list) = @_;

my (\$largest, \$secondlargest);

for(my \$i = 0;\$i<=\$#list;\$i++)
{
if(\$i == 0)
{
if(\$list[0] >= \$list[1])
{
(\$largest, \$secondlargest) = (\$list[0], \$list[1]);
}
else
{
(\$largest, \$secondlargest) = (\$list[1], \$list[0]);
}
}
if(\$i >=3)
{
if(\$list[\$i] >= \$largest)
{
\$secondlargest = \$largest;
\$largest = \$list[\$i];
}
elsif(\$list[\$i] >= \$secondlargest)
{
\$secondlargest = \$list[\$i];
}
}
}
return \$secondlargest;
}
Re: How to get 2nd highest value from an array?
by GrandFather (Saint) on Dec 14, 2005 at 01:39 UTC

Non-sorted hash values or array compatible version:

```use warnings;
use strict;

my %hash = (4 => '1', 5 => '5', 7 => '2', 1 => '7', 10 => '9', 3 => '0
+', 2 => '3', 9 => '8');

print GetSecondLargest(values %hash);

sub GetSecondLargest
{
my @largest = (shift);

while (@_)
{
my \$new = shift;
if (\$new >= \$largest [-1])
{
unshift @largest, \$new;
next;
}

\$largest[1] = \$new if ! \$#largest or \$new > \$largest[1];
}

return \$#largest ? \$largest[1] : undef;
}

Prints:

8

DWIM is Perl's answer to Gödel
Re: How to get 2nd highest value from an array?
by Nilotpal_1984 (Initiate) on Jun 24, 2017 at 05:09 UTC
```# code to get second highest number without sort.
#!/usr/bin/perl

use strict ;

my @arr = qw(4 4 0 -1 -2 2 0 1) ;

my \$f = \$arr[0] ;
my \$s = \$arr[0] ;

for (my \$i=1 ; \$i<@arr; \$i++) {
if (\$arr[\$i] > \$f) {
\$s = \$f ;
\$f = \$arr[\$i] ;
} elsif ((\$arr[\$i] > \$s || ((\$f == \$s))) && \$arr[\$i]!=\$f) {
\$s = \$arr[\$i] ;
}
}
if (\$f == \$s) {
print "\n there is no second greatest number" ;
} else {
print "\n second highest number : \$s" ;
}
Re: How to get 2nd highest value from an array?
by l.frankline (Hermit) on Dec 14, 2005 at 03:59 UTC

Hi,

A simplest way u can try...

```@arr = (1..10);
print sort(\$arr[\$#arr]-1);

Regards
Franklin

Don't put off till tomorrow, what you can do today.

Well the code above prints value-1 of the last element not the value of the next to last element. In an array of sequential numbers the result may be the same ie element 9 contains value 9.

So the print statement becomes

```print sort(\$arr[\$#arr-1]);
?

Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://516453]
Approved by GrandFather
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others lurking in the Monastery: (3)
As of 2024-03-02 03:52 GMT
Voting Booth?
My favourite way to spend a leap day ...

Results (29 votes). Check out past polls.