C# 获取最大元素的索引
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1136174/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Obtain the Index of the Maximum Element
提问by Graviton
Given such a list:
鉴于这样的列表:
List<int> intList = new List<int>();
intList.Add(5);
intList.Add(10);
intList.Add(15);
intList.Add(46);
how do you obtain the index of the maximum element in the list? In this case, it's at index 3.
你如何获得列表中最大元素的索引?在本例中,它位于索引 3。
Edit: It's a shame that standard LINQ doesn't ship this functionalities.
编辑:很遗憾标准 LINQ 没有提供此功能。
采纳答案by jpbochi
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.
在
!intList.Any() ? -1 :
将迫使-1
如果列表是空的;在
Select
将项目中的每个int
元素为一个匿名类型具有两个属性:Value
和Index
;该
Aggregate
会得到最高的元素Value
;最后,我们得到
Index
所选元素的 。
* 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.
** 期间分配大量新对象Select
可能是浪费。正如一些人测试的那样,它在大型列表中表现不佳。
EDIT 1:empty list check added.
编辑 1:添加了空列表检查。
EDIT 2:added caveats about performance.
编辑 2:添加了有关性能的警告。
回答by Sadegh
this way :
这边走 :
var maxIndex = foo.IndexOf(foo.Max());
回答by Clement Herreman
Use a custom function, using Max() and IndexOf() cost more.
使用自定义函数,使用 Max() 和 IndexOf() 成本更高。
回答by Kyle Rozendo
Here's the non-linq method if you like:
如果您愿意,这里是非 linq 方法:
private int ReturnMaxIdx(List<int> intList)
{
int MaxIDX = -1;
int Max = -1;
for (int i = 0; i < intList.Count; i++)
{
if (i == 0)
{
Max = intList[0];
MaxIDX = 0;
}
else
{
if (intList[i] > Max)
{
Max = intList[i];
MaxIDX = i;
}
}
}
return MaxIDX;
}
This is a single pass through the list at least.
这至少是一次遍历列表。
Hope this helps,
希望这可以帮助,
Kyle
凯尔
回答by Jon Skeet
Here's a custom LINQ method which I believe does what you want. (I previously had another which does a projection, but you can just call Select to do that, as you only need the index.)
这是一个自定义的 LINQ 方法,我相信它可以满足您的需求。(我以前有另一个进行投影,但您可以调用 Select 来执行此操作,因为您只需要索引。)
public static int MaxIndex<T>(this IEnumerable<T> source)
{
IComparer<T> comparer = Comparer<T>.Default;
using (var iterator = source.GetEnumerator())
{
if (!iterator.MoveNext())
{
throw new InvalidOperationException("Empty sequence");
}
int maxIndex = 0;
T maxElement = iterator.Current;
int index = 0;
while (iterator.MoveNext())
{
index++;
T element = iterator.Current;
if (comparer.Compare(element, maxElement) > 0)
{
maxElement = element;
maxIndex = index;
}
}
return maxIndex;
}
}
回答by Matt Howells
I can't improve on Jon Skeet's answer for the general case, so I am going for the 'high performance' prize in the specific case of a list of ints.
我无法改进 Jon Skeet 对一般情况的回答,因此我将在整数列表的特定情况下获得“高性能”奖。
public static class Extensions
{
public static int IndexOfMaximumElement(this IList<int> list)
{
int size = list.Count;
if (size < 2)
return size - 1;
int maxValue = list[0];
int maxIndex = 0;
for (int i = 1; i < size; ++i)
{
int thisValue = list[i];
if (thisValue > maxValue)
{
maxValue = thisValue;
maxIndex = i;
}
}
return maxIndex;
}
回答by LukeH
Here's how to do it in one (long) line using LINQ, with just a single pass through the collection. It should work for any IEnumerable<int>
, not just lists.
以下是如何使用 LINQ 在一行(长)行中执行此操作,只需通过集合一次即可。它应该适用于任何IEnumerable<int>
,而不仅仅是列表。
int maxIndex = intList
.Select((x, i) => new { Value = x, Index = i })
.Aggregate
(
new { Value = int.MinValue, Index = -1 },
(a, x) => (a.Index < 0) || (x.Value > a.Value) ? x : a,
a => a.Index
);
Here's the non-LINQ equivalent of the above, using a foreach
loop. (Again, just a single pass through the collection, and should work for any IEnumerable<int>
.)
这是使用foreach
循环的上述非 LINQ 等效项。(同样,只需一次通过集合,应该适用于任何IEnumerable<int>
.)
int maxIndex = -1, maxValue = int.MinValue, i = 0;
foreach (int v in intList)
{
if ((maxIndex < 0) || (v > maxValue))
{
maxValue = v;
maxIndex = i;
}
i++;
}
If you know that the collection is an IList<int>
then a plain for
loop is probably the easiest solution:
如果您知道集合是一个,IList<int>
那么简单的for
循环可能是最简单的解决方案:
int maxIndex = -1, maxValue = int.MinValue;
for (int i = 0; i < intList.Count; i++)
{
if ((maxIndex < 0) || (intList[i] > maxValue))
{
maxValue = intList[i];
maxIndex = i;
}
}
回答by Alex
Here is my solution:
这是我的解决方案:
public static int IndexOfMax(this IList<int> source)
{
if (source == null)
throw new ArgumentNullException("source");
if (source.Count == 0)
throw new InvalidOperationException("List contains no elements");
int maxValue = source[0];
int maxIndex = 0;
for (int i = 1; i < source.Count; i++)
{
int value = source[i];
if (value > maxValue)
{
maxValue = value;
maxIndex = i;
}
}
return maxIndex;
}
回答by Aelphaeis
public static class Extensions
{
public static int MaxIndex<T>(this IEnumerable<T> TSource)
{
int i = -1;
using (var iterator = TSource.GetEnumerator())
while (iterator.MoveNext())
i++;
return i;
}
}
Here is my crack at this problem. I returned -1 instead of throwing an exception because this is what the FindIndex function does and I find it very convenient.
这是我对这个问题的破解。我返回 -1 而不是抛出异常,因为这是 FindIndex 函数所做的,而且我发现它非常方便。