Beefy Boxes and Bandwidth Generously Provided by pair Networks
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 ( [id://516453] : perlquestion . print w/replies, xml ) 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---
    (the triplet paradiddle with high-hat)
    
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]);
      ?