获取最大元素的索引

给出这样一个清单:

List intList = new List(); intList.Add(5); intList.Add(10); intList.Add(15); intList.Add(46); 

你如何获得列表中最大元素的索引? 在这种情况下,它在索引3处。

编辑:标准LINQ不提供此function是一种遗憾。

这是一个简单*且相对有效的**解决方案:

 int indexMax = !intList.Any() ? -1 : intList .Select( (value, index) => new { Value = value, Index = index } ) .Aggregate( (a, b) => (a.Value > b.Value) ? a : b ) .Index; 
  1. !intList.Any() ? -1 : !intList.Any() ? -1 :如果列表为空,将强制-1 ;

  2. Select会将每个int元素投影到一个具有两个属性的匿名类型: ValueIndex ;

  3. Aggregate将获得具有最高Value的元素;

  4. 最后,我们得到所选元素的Index

*简单是相对的。 这里的目的是达到可读性的平衡,并且仍然只扫描列表一次。

**在Select期间分配大量新对象可能很浪费。 有些人测试过,它对大型列表表现不佳。

编辑1:添加空列表检查。

编辑2:增加了关于性能的警告。

这条路 :

 var maxIndex = foo.IndexOf(foo.Max()); 

这是一个自定义LINQ方法,我相信你做的就是你想要的。 (我之前有另一个做投影的人,但你只需要调用Select即可,因为你只需要索引。)

 public static int MaxIndex(this IEnumerable source) { IComparer comparer = Comparer.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; } } 

以下是使用LINQ在一条(长)行中执行此操作的方法,只需一次通过集合即可。 它应该适用于任何IEnumerable ,而不仅仅是列表。

 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 ); 

这是使用foreach循环的上述非LINQ等价物。 (同样,只需要通过集合一次,并且应该适用于任何IEnumerable 。)

 int maxIndex = -1, maxValue = int.MinValue, i = 0; foreach (int v in intList) { if ((maxIndex < 0) || (v > maxValue)) { maxValue = v; maxIndex = i; } i++; } 

如果您知道该集合是IList那么plain 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; } } 

我无法改进Jon Skeet对一般案例的回答,因此我将在一份特定案例中获得“高绩效”奖。

 public static class Extensions { public static int IndexOfMaximumElement(this IList 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; } 

如果您愿意,这是非linq方法:

 private int ReturnMaxIdx(List 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; } 

这至少是单次通过列表。

希望这可以帮助,

凯尔

使用自定义函数,使用Max()和IndexOf()花费更多。

这是我的解决方案:

 public static int IndexOfMax(this IList 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; } 
 public static class Extensions { public static int MaxIndex(this IEnumerable TSource) { int i = -1; using (var iterator = TSource.GetEnumerator()) while (iterator.MoveNext()) i++; return i; } } 

这是我解决这个问题的方法。 我返回-1而不是抛出exception,因为这是FindIndex函数的作用,我发现它非常方便。