获取最大元素的索引

时间:2009-07-16 08:26:44

标签: c# linq

给出这样的清单:

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

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

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

9 个答案:

答案 0 :(得分:35)

这样:

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

答案 1 :(得分: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;
  1. 如果列表为空,!intList.Any() ? -1 :将强制-1;

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

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

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

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

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

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

    编辑2:增加了关于效果的警告。

答案 2 :(得分:11)

这是一个自定义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;
    }
}

答案 3 :(得分: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
        );

这是使用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++;
}

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

答案 4 :(得分:3)

我无法改进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;
    }

答案 5 :(得分:1)

如果您愿意,这是非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;
        }

这至少是单次通过列表。

希望这有帮助,

凯尔

答案 6 :(得分:0)

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

答案 7 :(得分:0)

这是我的解决方案:

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

答案 8 :(得分:0)

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

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