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
  • Comment on How to get 2nd highest value from an array?

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]);
      ?