How do I get the index of the highest value in an array using LINQ?
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.
How to use linq to find the index of the item with the highest value
var f = Data.First();
var m = 0;
var result = Data.Select((v, i) => (v > f ? f = v > f ? m = i : m = m : m )).Max();
Edit: Updated/Changed
Finding Index of Array of maximum length in a List?
You can try general aggregating method Aggregate
instead of specific Max
:
var index = list
.Select((array, index) => (array, index))
.Aggregate((s, a) => s.array.Length > a.array.Length ? s : a)
.index;
How can I get LINQ to return the index of the object which has the max value in a collection?
Well, if you wanted to, you could of course write an IndexOfMaxBy
extension 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);
Obtain the index of the maximum element
Here is a simple* and relatively efficient** solution:
int indexMax
= !intList.Any() ? -1 :
intList
.Select( (value, index) => new { Value = value, Index = index } )
.Aggregate( (a, b) => (a.Value > b.Value) ? a : b )
.Index;
The
!intList.Any() ? -1 :
will force a-1
if the list is empty;The
Select
will project eachint
element into an anonymous type with two properties:Value
andIndex
;The
Aggregate
will get the element with the highestValue
;Finally, we get the
Index
of the chosen element.
* Simplicity is relative. The aim here was to reach a balance of readability and still only scan the list once.
** The allocation of lots of new objects during the Select
is probably wasteful. As some people tested, it doesn't perform well for large lists.
EDIT 1: empty list check added.
EDIT 2: added caveats about performance.
C# find highest array value and index
This is not the most glamorous way but works.
(must have using System.Linq;
)
int maxValue = anArray.Max();
int maxIndex = anArray.ToList().IndexOf(maxValue);
How to get the index of the biggest number in array?
You can use IEnumerable.Max()
method like;
Returns the maximum value in a sequence of values.
float[] sizeEdge = new float[] { 12f, 43f, 556f, 98f };
int maxIndex = Array.IndexOf(sizeEdge, sizeEdge.Max());
Console.WriteLine(sizeEdge[maxIndex]);
Result will be;
556
Here a DEMO
.
Related Topics
How to Get the Local MAChine Name in C#
Interesting "Params of Ref" Feature, Any Workarounds
Run .Exe Executable File in Azure Function
Detect If Geolocation Is in Complex Polygon or Not
Jquery Ajax Calls to Web Service Seem to Be Synchronous
Custom Authentication in ASP.NET-Core
Design Pattern for Handling Multiple Message Types
How to Check If a File Exists in a Folder
C# Wait for User to Finish Typing in a Text Box
Does Garbage Collector Call Dispose()
How to Implement Automatic Sorting of Datagridview
Compile-Time and Runtime Casting C#
Caliburn.Micro Serialization Issue When Implementing Propertychangedbase
Error Making Azure Management Library API Call When Authenticating with Azure Active Directory