我有一个双打数组,我想要最高值的索引.这些是我到目前为止提出的解决方案,但我认为必须有一个更优雅的解决方案.想法?
double[] score = new double[] { 12.2, 13.3, 5, 17.2, 2.2, 4.5 }; int topScoreIndex = score.Select((item, indx) => new {Item = item, Index = indx}).OrderByDescending(x => x.Item).Select(x => x.Index).First(); topScoreIndex = score.Select((item, indx) => new {Item = item, Index = indx}).OrderBy(x => x.Item).Select(x => x.Index).Last(); double maxVal = score.Max(); topScoreIndex = score.Select((item, indx) => new {Item = item, Index = indx}).Where(x => x.Item == maxVal).Select(x => x.Index).Single();
Jon Skeet.. 44
我建议编写自己的扩展方法(编辑为带有IComparable
约束的泛型.)
public static int MaxIndex(this IEnumerable sequence) where T : IComparable { int maxIndex = -1; T maxValue = default(T); // Immediately overwritten anyway int index = 0; foreach (T value in sequence) { if (value.CompareTo(maxValue) > 0 || maxIndex == -1) { maxIndex = index; maxValue = value; } index++; } return maxIndex; }
请注意,如果序列为空,则返回-1.
关于特点的一句话:
这适用于只能枚举一次的序列 - 这有时非常重要,并且通常是IMO的理想特征.
内存复杂度为O(1)(与排序的O(n)相反)
运行时复杂度为O(n)(与排序的O(n log n)相反)
至于这个"是否是LINQ":如果它被列为标准LINQ查询运算符之一,你会把它算作LINQ吗?它是否感觉特别陌生或与其他LINQ运营商不同?如果MS将它作为新运算符包含在.NET 4.0中,它会是LINQ吗?
编辑:如果你真的,真的非常喜欢使用LINQ(而不仅仅是获得一个优雅的解决方案),那么这里仍然是O(n)并且只评估序列一次:
int maxIndex = -1; int index=0; double maxValue = 0; int urgh = sequence.Select(value => { if (maxIndex == -1 || value > maxValue) { maxIndex = index; maxValue = value; } index++; return maxIndex; }).Last();
这很可怕,我建议你不要使用它 - 但它会起作用.
我建议编写自己的扩展方法(编辑为带有IComparable
约束的泛型.)
public static int MaxIndex(this IEnumerable sequence) where T : IComparable { int maxIndex = -1; T maxValue = default(T); // Immediately overwritten anyway int index = 0; foreach (T value in sequence) { if (value.CompareTo(maxValue) > 0 || maxIndex == -1) { maxIndex = index; maxValue = value; } index++; } return maxIndex; }
请注意,如果序列为空,则返回-1.
关于特点的一句话:
这适用于只能枚举一次的序列 - 这有时非常重要,并且通常是IMO的理想特征.
内存复杂度为O(1)(与排序的O(n)相反)
运行时复杂度为O(n)(与排序的O(n log n)相反)
至于这个"是否是LINQ":如果它被列为标准LINQ查询运算符之一,你会把它算作LINQ吗?它是否感觉特别陌生或与其他LINQ运营商不同?如果MS将它作为新运算符包含在.NET 4.0中,它会是LINQ吗?
编辑:如果你真的,真的非常喜欢使用LINQ(而不仅仅是获得一个优雅的解决方案),那么这里仍然是O(n)并且只评估序列一次:
int maxIndex = -1; int index=0; double maxValue = 0; int urgh = sequence.Select(value => { if (maxIndex == -1 || value > maxValue) { maxIndex = index; maxValue = value; } index++; return maxIndex; }).Last();
这很可怕,我建议你不要使用它 - 但它会起作用.
嗯,为什么要让它过于复杂?这是最简单的方法.
var indexAtMax = scores.ToList().IndexOf(scores.Max());
是的,您可以使用扩展方法来减少内存使用量,但除非您处理大型数组,否则您将永远不会注意到这种差异.
var scoreList = score.ToList(); int topIndex = ( from x in score orderby x select scoreList.IndexOf(x) ).Last();
如果score
不是一个数组,这不会是一半坏...