Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I get the index of the highest value in an array using LINQ?

Tags:

c#

linq

I have an array of doubles and I want the index of the highest value. These are the solutions that I've come up with so far but I think that there must be a more elegant solution. Ideas?

double[] score = new double[] { 12.2, 13.3, 5, 17.2, 2.2, 4.5 }; int topScoreIndex = score.Select((item, indx) => new {Item = item, Index = indx}).OrderByDescending(x => x.Item).Select(x => x.Index).First();  topScoreIndex = score.Select((item, indx) => new {Item = item, Index = indx}).OrderBy(x => x.Item).Select(x => x.Index).Last();  double maxVal = score.Max(); topScoreIndex = score.Select((item, indx) => new {Item = item, Index = indx}).Where(x => x.Item == maxVal).Select(x => x.Index).Single(); 
like image 382
Guy Avatar asked Jan 20 '09 19:01

Guy


People also ask

How do you find the index of an element in LINQ?

LINQ does not have an IndexOf method. So to find out index of a specific item we need to use FindIndex as int index = List. FindIndex(your condition); 0.

Can LINQ query work with array?

Query writing in LINQLINQ allows us to write query against all data whether it comes from array, database, XML etc.


2 Answers

Meh, why make it overcomplicated? This is the simplest way.

var indexAtMax = scores.ToList().IndexOf(scores.Max()); 

Yeah, you could make an extension method to use less memory, but unless you're dealing with huge arrays, you will never notice the difference.

like image 155
PJ7 Avatar answered Sep 23 '22 04:09

PJ7


I suggest writing your own extension method (edited to be generic with an IComparable<T> constraint.)

public static int MaxIndex<T>(this IEnumerable<T> sequence)     where T : IComparable<T> {     int maxIndex = -1;     T maxValue = default(T); // Immediately overwritten anyway      int index = 0;     foreach (T value in sequence)     {         if (value.CompareTo(maxValue) > 0 || maxIndex == -1)         {              maxIndex = index;              maxValue = value;         }         index++;     }     return maxIndex; } 

Note that this returns -1 if the sequence is empty.

A word on the characteristics:

  • This works with a sequence which can only be enumerated once - this can sometimes be very important, and is generally a desirable feature IMO.
  • The memory complexity is O(1) (as opposed to O(n) for sorting)
  • The runtime complexity is O(n) (as opposed to O(n log n) for sorting)

As for whether this "is LINQ" or not: if it had been included as one of the standard LINQ query operators, would you count it as LINQ? Does it feel particularly alien or unlike other LINQ operators? If MS were to include it in .NET 4.0 as a new operator, would it be LINQ?

EDIT: If you're really, really hell-bent on using LINQ (rather than just getting an elegant solution) then here's one which is still O(n) and only evaluates the sequence once:

int maxIndex = -1; int index=0; double maxValue = 0;  int urgh = sequence.Select(value => {     if (maxIndex == -1 || value > maxValue)     {         maxIndex = index;         maxValue = value;     }     index++;     return maxIndex;  }).Last(); 

It's hideous, and I don't suggest you use it at all - but it will work.

like image 21
Jon Skeet Avatar answered Sep 22 '22 04:09

Jon Skeet