linq 获取最大元素的索引

brtdzjyr  于 12个月前  发布在  其他
关注(0)|答案(9)|浏览(99)

给出这样一个列表:

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

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

kcwpcxri

kcwpcxri1#

这样:

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

wydwbb8l2#

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

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;

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

toiithl63#

这里有一个自定义的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;
    }
}
63lcw9qa

63lcw9qa4#

下面是如何使用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
        );

下面是上面的非LINQ等价物,使用foreach循环。(同样,只需一次遍历集合,并且应该适用于任何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;
    }
}
7kqas0il

7kqas0il5#

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

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

gopyfrb36#

以下是我的解决方案:

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

pvabu6sv7#

如果你喜欢,这里是非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;
        }

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

mfuanj7w

mfuanj7w8#

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

q35jwt9p

q35jwt9p9#

简化.

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

相关问题