给出这样的清单:
List<int> intList = new List<int>();
intList.Add(5);
intList.Add(10);
intList.Add(15);
intList.Add(46);
如何获取列表中最大元素的索引?在这种情况下,它在索引3处。
编辑:遗憾的是标准LINQ没有提供这些功能。
答案 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;
如果列表为空,!intList.Any() ? -1 :
将强制-1
;
Select
会将每个int
元素投影为具有两个属性的匿名类型:Value
和Index
;
Aggregate
将获得具有最高Value
的元素;
最后,我们得到所选元素的Index
。
*简单是相对的。这里的目的是达到可读性的平衡,并且仍然只扫描一次列表。
**在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函数的作用,我发现它非常方便。