Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I get LINQ to return the index of the object which has the max value in a collection?

I have a list of immutable objects (in my specific case a list of Tuple<double, double>) and I'd like to change the one with the highest Item2 value.

Ideally there would be an IndexOfMaxBy function I could use, so I could do:

var indexOfPointWithHighestItem2 = myList.IndexOfMaxBy(x => x.Item2);

var original = myList[indexOfPointWithHighestItem2];

myList[indexOfPointWithHighestItem2] = 
  new Tuple<double, double>(original.Item1, original.Item2 - 1);

I have seen How can I get LINQ to return the object which has the max value for a given property?, and using Jon Skeet's MaxBy function combined with Select I could do:

var indexOfPointWithHighestItem2 = 
  myList.Select((x, i) => new { Index = i, Value = x })
        .MaxBy(x => x.Item2).Index;

But this creates a new object for every object in my list, and there must be a neater way. Does anyone have any good suggestions?

like image 625
dominic Avatar asked Mar 04 '11 03:03

dominic


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.

How to get max value in LINQ query?

In LINQ, you can find the maximum element of the given sequence by using Max() function. This method provides the maximum element of the given set of values.

How do you find the minimum and maximum value in LINQ?

In LINQ, you can find the minimum element of the given sequence by using Min() function. This method provides the minimum element of the given set of values. It does not support query syntax in C#, but it supports in VB.NET. It is available in both Enumerable and Queryable classes in C#.

What is Max in LINQ?

Max () function in LINQ is used to return the maximum value from the collection. With the help of Max() function, it is easy to find the maximum value from a given data source using Max () function. In the other case, we have to write the code to get the maximum value from the list of values.


2 Answers

It looks like there is a FindIndex method defined on List that would be perfect for this:

double max = myList.Max(t => t.Item2);
int index = myList.FindIndex(t => t.Item2 == max);
like image 59
mellamokb Avatar answered Oct 15 '22 23:10

mellamokb


Well, if you wanted to, you could of course write an IndexOfMaxByextension yourself.

Example(untested):

public static int IndexOfMaxBy<TSource, TProjected>
    (this IEnumerable<TSource> source,
     Func<TSource, TProjected> selector,
     IComparer<TProjected> comparer = null
    )
{

    //null-checks here

    using (var erator = source.GetEnumerator())
    {
        if (!erator.MoveNext())
            throw new InvalidOperationException("Sequence is empty.");

        if (comparer == null)
            comparer = Comparer<TProjected>.Default;

        int index = 0, maxIndex = 0;
        var maxProjection = selector(erator.Current);

        while (erator.MoveNext())
        {
            index++;
            var projectedItem = selector(erator.Current);

            if (comparer.Compare(projectedItem, maxProjection) > 0)
            {
                maxIndex = index;
                maxProjection = projectedItem;
            }
        }
        return maxIndex;
    }
}

Usage:

var indexOfPointWithHighestItem2 = myList.IndexOfMaxBy(x => x.Item2);
like image 33
Ani Avatar answered Oct 15 '22 22:10

Ani