Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

How can I find the index of the biggest element in an array?

by Anonymous Monk
on Mar 08, 2001 at 08:03 UTC ( [id://62913]=perlquestion: print w/replies, xml ) Need Help??

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question: (arrays)

How can I find the index of the biggest element in an array?

Originally posted as a Categorized Question.

  • Comment on How can I find the index of the biggest element in an array?

Replies are listed 'Best First'.
Re: How can I find the index of the biggest element in an array?
by GrandFather (Saint) on May 27, 2007 at 22:53 UTC

    Given an array @data containing numeric data:

    my $idxMax = 0; $data[$idxMax] > $data[$_] or $idxMax = $_ for 1 .. $#data;

    is not only compact but, somewhat surprisingly perhaps, comparable in speed to caching $data[$idxMax] as shown in most of the other variants. A cache variant is worth using if an expensive calculation is required in the comparison or a very large array is being processed.

Re: How can I find the index of the biggest element in an array?
by tye (Sage) on Mar 08, 2001 at 11:03 UTC
    my $index = 0; my $maxval = $myarray[ $index ]; for my $i ( 0 .. $#myarray ) { $maxval < $myarray[$i] and $index = $i if $maxval < $myarray[$i]; } print "The greatest is element number $index: $myarray[$index]\n";
Re: How can I find the index of the biggest element in an array?
by satchboost (Scribe) on Mar 14, 2001 at 22:16 UTC
    my $index = 0; my $maxval = $myarray[ my $index ]; for ( 0 .. $#myarray ) { if ( $maxval < $myarray[$_] ) { $index = $_; $maxval = $myarray[$_]; } } print "Max is index $index: $myarray[$index]\n";
Re: How can I find the index of the biggest element in an array?
by turnstep (Parson) on Mar 08, 2001 at 08:06 UTC
    my $max; my $index; my $x = 0; for ( @myarray ) { $index = $x and $max = $_ if !defined $max or $_ > $max; $x++; } print "The winner is element number $index: $myarray[$index]\n";
      There's still a bug, if the biggest element is at index 0
Re: How can I find the index of the biggest element in an array?
by reisinge (Hermit) on Mar 14, 2017 at 13:35 UTC
    A one-liner where the array elements are the command line arguments:
    $ perl -E 'say [ sort { $ARGV[$b] <=> $ARGV[$a] } 0..$#ARGV ]->[0]' 42 + 1000 999 0 -1

      I was wondering about the efficiency of this solution so I compared it with GrandFather's solution:

      # x.pl use Benchmark qw(timethese cmpthese); cmpthese( -2, { GrandFather => sub { my $idxMax = 0; $ARGV[$idxMax] > $ARGV[$_] or $idxMax = $_ for 1 .. $#ARGV +; $idxMax; }, reisinge => sub { [ sort { $ARGV[$b] <=> $ARGV[$a] } 0..$#ARGV ]->[0]; } } );

      These are the results of the benchmarking:

      $ perl x.pl $(seq 1 1000) Rate reisinge GrandFather reisinge 3742/s -- -3% GrandFather 3864/s 3% -- $ perl x.pl $(seq 1 10000) Rate reisinge GrandFather reisinge 377/s -- -5% GrandFather 395/s 5% -- $ perl x.pl $(seq 1 100000) Rate reisinge GrandFather reisinge 34.1/s -- -18% GrandFather 41.6/s 22% --

      GrandFathers's solution seems to be more efficient, i.e. it's faster (to run) and scales better. But mine is shorter :-).

      It all comes to this: the simplest way to be happy is to do good. -- Helen Keller

        GrandFather's solution may be shorten if a short one-liner is what you're after.

        # reisinge perl -E 'say [ sort { $ARGV[$b] <=> $ARGV[$a] } 0..$#ARGV ]->[0]' 42 1 +000 999 0 -1 # GrandFather perl -E '$m=0; $ARGV[$m] > $ARGV[$_] or $m=$_ for 1..$#ARGV; say $m' 4 +2 1000 999 0 -1 # Shorten, similar performance perl -E '$i=0; ($ARGV[$m] > $_ or $m=$i), $i++ for @ARGV; say $m' 42 1 +000 999 0 -1

        Below, please find a benchmark script for testing against a large list.

        use strict; use warnings; use List::Util 'shuffle'; use Time::HiRes 'time'; # Return index to biggest element. sub reisinge { [ sort { $_[$b] <=> $_[$a] } 0 .. $#_ ]->[0]; } sub GrandFather { my $idxMax = 0; $_[$idxMax] > $_[$_] or $idxMax = $_ for 1 .. $#_; $idxMax; } sub biggest_elm { my ($idxMax,$idx) = (0,0); ($_[$idxMax] > $_ or $idxMax = $idx), $idx++ for @_; $idxMax; } srand 0; my @list = shuffle 1..4e5; for my $code (qw( reisinge GrandFather biggest_elm )) { no strict 'refs'; my ($start, $idx) = (time, $code->(@list)); printf "Index %d, Seconds (%-11s): %0.03f\n", $idx, $code, time - $start; }

        Regards, Mario.

        Edit: Added benchmark script.

Re: How can I find the index of the biggest element in an array?
by DillonYu (Novice) on Mar 14, 2017 at 08:21 UTC
    Use mod:://List::Util's reduce:
    use List::Util qw /reduce/; my @arr= qw/7 6 4 90 5 7/; my $index = reduce {$arr[$a] > $arr[$b] ? $a : $b} (0 .. $#arr); print "$index\n";
Re: How can I find the index of the biggest element in an array?
by salva (Canon) on May 27, 2007 at 22:15 UTC
    and if what you need are the indexes for the $n biggest elements:
    use Sort::Key::Top qw(nkeytop rnkeytop); my @data = ( 100, -2, 5, 12, 1, 1, 6786, ...); my @min_ix_n = nkeytop { @data[$_] } $n => 0..$#data; my @max_ix_n = rnkeytop { @data[$_] } $n => 0..$#data;
Re: How can I find the index of the biggest element in an array?
by Skeeve (Parson) on May 28, 2007 at 08:30 UTC

    turnstep's first answer has two bugs

    1. He forgot to set $maxval after fiding a longer string
    2. He forgot to consider index 0

    Originally posted as a Categorized Answer.

Re: How can I find the index of the biggest element in an array?
by jdporter (Paladin) on Feb 18, 2013 at 14:39 UTC

    A recursive solution.

    sub _index_of_largest { my $X = shift; my $L = shift; my $x = $#_; my $l = pop; defined $X and $L > $l and ($x,$l) = ($X,$L); @_ or return $x; unshift @_, $x, $l; goto &_index_of_largest } sub index_of_largest { @_ or die; _index_of_largest(undef,undef,@_); } my $i = index_of_largest( @a );
Re: How can I find the index of the biggest element in an array?
by EdgeNosedMonkey (Initiate) on Feb 17, 2013 at 18:32 UTC
    I missed the square brackets in the previous reply:

    %arrayHash=map {$_=> $i++} @array=(5,4,3,2,7); print $arrayHash{pop [sort @array]};

    Originally posted as a Categorized Answer.

Re: How can I find the index of the biggest element in an array?
by EdgeNosedMonkey (Initiate) on Feb 17, 2013 at 18:55 UTC
    Also if your question is specifically about finding the largest number, the following code should work just fine :
    %arrayHash=map {$_=> $i++} @array=(-15,4,8,10,3,2,7); print $arrayHash{pop [sort {$a<=>$b} @array]};

    Originally posted as a Categorized Answer.

Re: How can I find the index of the biggest element in an array?
by Skeeve (Parson) on May 27, 2007 at 18:57 UTC
    my $i = $#data; my $max = $i; $max = $data[$i] > $data[$max] ? $i : $max while $i--; print "Max value is $data[$max], at index $max\n"

      I don't think it's good to scare people with a ternary operator and statement modifier in one statement. I do think

      while ($i--) { $max = $i if $data[$i] > $data[$max]; }
      would be much more readable. I'd probably write it like this though:
      my $max = 0; for (0 .. $#data) { $max = $_ if $data[$_] > $data[$max] }

      Update (suggested by ysth): It's actually better to start looping at index 1:

      my $max = 0; for (1 .. $#data) { $max = $_ if $data[$_] > $data[$max] }
      There's no point in comparing the first element to itself.

    A reply falls below the community's threshold of quality. You may see it by logging in.
Re: How can I find the index of the biggest element in an array?
by simmisam (Novice) on Jan 15, 2014 at 21:50 UTC
    my @array1 = qw(4 3 7 8 9 49 12 23 43); my $largest = (sort {$b <=> $a} @array1)[0]; my ($index) = grep {$array1[$_] ~~ $largest} 0..$#array1; print "Number = $largest, Index = $index\n";
      I disagree. This is kinda clever, but I suspect that a single pass would be clearer. I would do this:
      my @array = qw(4 3 7 8 9 49 12 23 43); my ($largest, $largest_idx) = ($array1[0], 0); for my $i (1 .. $#array) { ($largest, $largest_idx) = ($array[$i], $i) if $largest < $array[$i]; } print "Largest number is $largest, at offset $largest_idx\n";
      It really seems like something like this should be available in List::Util or List::MoreUtils, and I would use one of those instead of the sort+smartmatch. At any rate, I am most likely to need this sort of calculation in PDL, where I would do it like this:
      use PDL; my $data = pdl(qw(4 3 7 8 9 49 12 23 43)); my $largest_idx = $data->maximum_ind; my $largest = $data->at($max_idx); print "Largest number is $largest, at offset $largest_idx\n";
      but PDL would be overkill for a dataset of this size.
Re: How can I find the index of the biggest element in an array?
by EdgeNosedMonkey (Initiate) on Feb 17, 2013 at 18:22 UTC

    You could use the Perl map function in the following way. This achieves the results in just two lines.


    %arrayHash=map {$_=> $i++} @array=(5,4,3,2,7); print $arrayHash{pop [sort @array]};

    Originally posted as a Categorized Answer.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://62913]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others imbibing at the Monastery: (3)
As of 2024-04-20 02:50 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found