获取最大元素的索引

Gra*_*ton 21 c# linq

给出这样一个清单:

        List<int> intList = new List<int>();
        intList.Add(5);
        intList.Add(10);
        intList.Add(15);
        intList.Add(46);
Run Code Online (Sandbox Code Playgroud)

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

编辑:遗憾的是标准LINQ没有提供这些功能.

Sad*_*egh 37

这条路 :

var maxIndex = foo.IndexOf(foo.Max());
Run Code Online (Sandbox Code Playgroud)

  • 它仍然是O(n),第二遍可能不是完整的传球.如果性能不是一个大问题,我会使用此代码. (6认同)
  • 这很简洁,但需要最多两次完整的遍历才能获得索引.如果你需要它更快,你应该使用for循环并随时跟踪索引. (3认同)

jpb*_*chi 16

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

int indexMax
    = !intList.Any() ? -1 :
    intList
    .Select( (value, index) => new { Value = value, Index = index } )
    .Aggregate( (a, b) => (a.Value > b.Value) ? a : b )
    .Index;
Run Code Online (Sandbox Code Playgroud)
  1. !intList.Any() ? -1 :将迫使-1如果列表是空的;

  2. Select将项目中的每个int元素为一个匿名类型具有两个属性:ValueIndex;

  3. Aggregate会得到最高的元素Value;

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

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

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

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

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

  • 不简单,不快. (3认同)
  • 也许它不像您想要的那么简单,但它是这里介绍的最快的。将其提取到扩展方法中并忘记它。我很想看看你的替代方案。因为您不喜欢而对最佳答案投反对票,这太幼稚了。 (2认同)

Jon*_*eet 12

这是一个自定义的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;
    }
}
Run Code Online (Sandbox Code Playgroud)


Luk*_*keH 7

以下是使用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
        );
Run Code Online (Sandbox Code Playgroud)

这是使用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++;
}
Run Code Online (Sandbox Code Playgroud)

如果您知道该集合是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;
    }
}
Run Code Online (Sandbox Code Playgroud)