linq 获取最大元素的索引

brtdzjyr  于 2023-09-28  发布在  其他
关注(0)|答案(9)|浏览(174)

给出这样一个列表:

  1. List<int> intList = new List<int>();
  2. intList.Add(5);
  3. intList.Add(10);
  4. intList.Add(15);
  5. intList.Add(46);

如何获得列表中最大元素的索引?在这种情况下,它的索引为3。
编辑:标准LINQ没有提供这些功能,这是一个遗憾。

kcwpcxri

kcwpcxri1#

这样:

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

wydwbb8l2#

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

  1. int indexMax
  2. = !intList.Any() ? -1 :
  3. intList
  4. .Select( (value, index) => new { Value = value, Index = index } )
  5. .Aggregate( (a, b) => (a.Value > b.Value) ? a : b )
  6. .Index;

1.如果列表为空,!intList.Any() ? -1 :将强制执行-1;

  1. Select将把每个int元素投影到一个匿名类型中,该类型具有两个属性:ValueIndex;
  2. Aggregate将得到Value最高的元素;
    1.最后,我们得到所选元素的Index
  • 简单是相对的。这里的目的是达到可读性的平衡,并且仍然只扫描列表一次。
    **在Select期间分配大量新对象可能是浪费的。正如一些人测试的那样,它在大列表中表现不佳。
    **EDIT 1:**增加空列表检查。
    **编辑2:**增加了关于性能的警告。
展开查看全部
toiithl6

toiithl63#

这里有一个自定义的LINQ方法,我相信它可以满足您的需求。(我以前有另一个做投影的,但你可以只调用Select来做,因为你只需要索引。

  1. public static int MaxIndex<T>(this IEnumerable<T> source)
  2. {
  3. IComparer<T> comparer = Comparer<T>.Default;
  4. using (var iterator = source.GetEnumerator())
  5. {
  6. if (!iterator.MoveNext())
  7. {
  8. throw new InvalidOperationException("Empty sequence");
  9. }
  10. int maxIndex = 0;
  11. T maxElement = iterator.Current;
  12. int index = 0;
  13. while (iterator.MoveNext())
  14. {
  15. index++;
  16. T element = iterator.Current;
  17. if (comparer.Compare(element, maxElement) > 0)
  18. {
  19. maxElement = element;
  20. maxIndex = index;
  21. }
  22. }
  23. return maxIndex;
  24. }
  25. }
展开查看全部
63lcw9qa

63lcw9qa4#

下面是如何使用LINQ在一个(长)行中完成此操作,只需一次遍历集合。它应该适用于任何IEnumerable<int>,而不仅仅是列表。

  1. int maxIndex = intList
  2. .Select((x, i) => new { Value = x, Index = i })
  3. .Aggregate
  4. (
  5. new { Value = int.MinValue, Index = -1 },
  6. (a, x) => (a.Index < 0) || (x.Value > a.Value) ? x : a,
  7. a => a.Index
  8. );

下面是上面的非LINQ等价物,使用foreach循环。(同样,只需一次遍历集合,并且应该适用于任何IEnumerable<int>

  1. int maxIndex = -1, maxValue = int.MinValue, i = 0;
  2. foreach (int v in intList)
  3. {
  4. if ((maxIndex < 0) || (v > maxValue))
  5. {
  6. maxValue = v;
  7. maxIndex = i;
  8. }
  9. i++;
  10. }

如果你知道集合是一个IList<int>,那么简单的for循环可能是最简单的解决方案:

  1. int maxIndex = -1, maxValue = int.MinValue;
  2. for (int i = 0; i < intList.Count; i++)
  3. {
  4. if ((maxIndex < 0) || (intList[i] > maxValue))
  5. {
  6. maxValue = intList[i];
  7. maxIndex = i;
  8. }
  9. }
展开查看全部
7kqas0il

7kqas0il5#

我无法改进Jon Skeet对一般情况的回答,所以我将在int列表的特定情况下获得“高性能”奖。

  1. public static class Extensions
  2. {
  3. public static int IndexOfMaximumElement(this IList<int> list)
  4. {
  5. int size = list.Count;
  6. if (size < 2)
  7. return size - 1;
  8. int maxValue = list[0];
  9. int maxIndex = 0;
  10. for (int i = 1; i < size; ++i)
  11. {
  12. int thisValue = list[i];
  13. if (thisValue > maxValue)
  14. {
  15. maxValue = thisValue;
  16. maxIndex = i;
  17. }
  18. }
  19. return maxIndex;
  20. }
展开查看全部
gopyfrb3

gopyfrb36#

以下是我的解决方案:

  1. public static int IndexOfMax(this IList<int> source)
  2. {
  3. if (source == null)
  4. throw new ArgumentNullException("source");
  5. if (source.Count == 0)
  6. throw new InvalidOperationException("List contains no elements");
  7. int maxValue = source[0];
  8. int maxIndex = 0;
  9. for (int i = 1; i < source.Count; i++)
  10. {
  11. int value = source[i];
  12. if (value > maxValue)
  13. {
  14. maxValue = value;
  15. maxIndex = i;
  16. }
  17. }
  18. return maxIndex;
  19. }
展开查看全部
pvabu6sv

pvabu6sv7#

如果你喜欢,这里是非linq方法:

  1. private int ReturnMaxIdx(List<int> intList)
  2. {
  3. int MaxIDX = -1;
  4. int Max = -1;
  5. for (int i = 0; i < intList.Count; i++)
  6. {
  7. if (i == 0)
  8. {
  9. Max = intList[0];
  10. MaxIDX = 0;
  11. }
  12. else
  13. {
  14. if (intList[i] > Max)
  15. {
  16. Max = intList[i];
  17. MaxIDX = i;
  18. }
  19. }
  20. }
  21. return MaxIDX;
  22. }

这至少是一次遍历列表。
希望这能帮上忙
凯尔

展开查看全部
mfuanj7w

mfuanj7w8#

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

q35jwt9p

q35jwt9p9#

简化.

  1. int MaxIndex = list.DefaultIfEmpty().Select((v, i) => new { v, i }).Aggregate((a, b) => (a.v > b.v) ? a : b).i;

相关问题