Enumerable.Max() 如果有两个最大值
Enumerable.Max() if two max values
我正在尝试从整数数组中获取最大值,但如果有两个值被认为是最大值,我需要在数组中找到它们的索引。
即如果我有数组:
{10, 13, 13, 9, 8}
我需要找到这 13 个值的索引
如果我有数组:
{10, 13, 12, 9, 8}
我只需要 return 13
的索引
我已经通过使用完成了第二部分
myArray.ToList().IndexOf(myArray.Max());
但是想不通第一个例子
试试这个:
private static IEnumerable<int> FindIndexesOfMax(int[] input)
{
int max = input.Max();
for (int i=0; i<input.Length; i++)
{
if (input[i] == max)
yield return i;
}
}
一点 LINQ 工作:
var numbers = new [] { 10, 13, 13, 9, 8 };
var maxIndices =
numbers
.Select((n, i) => new { n, i })
.GroupBy(x => x.n, x => x.i)
.OrderByDescending(x => x.Key)
.Take(1)
.SelectMany(x => x)
.ToArray();
这给出了结果:
记住数组是从零开始的,以上两个值是数组中 13
的索引。
你可以这样做:
var array = new int[] { 1, 2, 3, 4, 5, 3, 8, 2, 3, 6, 8, 8, 4, 3, 2, 8, 1, 8 };
var maxNumber = array.Max();
var indices =
array.Select((number, index) => number == maxNumber ? index : -1)
.Where(index => index != -1);
它返回所有最大数字索引的数组。我们为等于数组最大数的数字选择索引值,为每个其他值选择 -1。由于数组索引从零开始,我们永远不会得到 -1 作为数组最大数的索引。这意味着,在我们使用条件 index != -1
过滤我们的选择后,我们将只获得我们之前选择的最大数字的索引。
Fiddle 此处示例:https://dotnetfiddle.net/drRiVb
如果您需要与所有 linq 提供商合作(您在标题中提到的 Enumerable.Max()
而不是“Linq 的 Max()
表明您不需要,但也许您需要),那么我会建议 Enigmativity 的答案,但除非绝对需要,否则没有 ToArray()
。
如果你只关心枚举,我建议:
public static IEnumerable<int> MaxIndices(this IEnumerable<int> source)
{
using(var en = source.GetEnumerator())
{
if (!en.MoveNext())
return Enumerable.Empty<int>();
int curMax = en.Current;
List<int> indices = new List<int>{ 0 };
for (int index = 1; en.MoveNext(); ++index)
{
int current = en.Current;
if (current == curMax)
indices.Add(index);
else if (current > curMax)
{
indices.Clear();
indices.Add(index);
curMax = current;
}
}
return indices;
}
}
这通过返回一个空的可枚举开始(如果源中没有值,因此没有最大值)或者从包含 0
的列表开始作为起点始终是第一个元素是迄今为止找到的最大值。它从那个起点继续通过列表。如果给定元素与目前找到的最大值相匹配,则将其索引添加到索引列表中。如果给定元素大于目前找到的最大最小值,则它成为新的最大值,并且在添加其索引之前清除列表。否则该值将被忽略。
您可以将这两种方法与适当的重载相结合。除了以上还有:
public static IQueryable<int> MaxIndices(this IQueryable<int> source)
{
if (source is EnumerableQuery<int>)
return MaxIndices((IEnumerable<int>)source).AsQueryable(); // most efficient approach with enumerables.
return source.Select((n, i) => new { n, i })
.GroupBy(x => x.n, x => x.i)
.OrderByDescending(x => x.Key)
.FirstOrDefault() ?? Enumerable.Empty<int>().AsQueryable();
}
然后它对这两种情况都采用最有效的方法,包括将实际上可枚举的可查询对象视为可枚举对象。所有其他来源都与 Enigmativity 的回答中的一样对待。
我正在尝试从整数数组中获取最大值,但如果有两个值被认为是最大值,我需要在数组中找到它们的索引。
即如果我有数组: {10, 13, 13, 9, 8} 我需要找到这 13 个值的索引
如果我有数组: {10, 13, 12, 9, 8} 我只需要 return 13
的索引我已经通过使用完成了第二部分
myArray.ToList().IndexOf(myArray.Max());
但是想不通第一个例子
试试这个:
private static IEnumerable<int> FindIndexesOfMax(int[] input)
{
int max = input.Max();
for (int i=0; i<input.Length; i++)
{
if (input[i] == max)
yield return i;
}
}
一点 LINQ 工作:
var numbers = new [] { 10, 13, 13, 9, 8 };
var maxIndices =
numbers
.Select((n, i) => new { n, i })
.GroupBy(x => x.n, x => x.i)
.OrderByDescending(x => x.Key)
.Take(1)
.SelectMany(x => x)
.ToArray();
这给出了结果:
记住数组是从零开始的,以上两个值是数组中 13
的索引。
你可以这样做:
var array = new int[] { 1, 2, 3, 4, 5, 3, 8, 2, 3, 6, 8, 8, 4, 3, 2, 8, 1, 8 };
var maxNumber = array.Max();
var indices =
array.Select((number, index) => number == maxNumber ? index : -1)
.Where(index => index != -1);
它返回所有最大数字索引的数组。我们为等于数组最大数的数字选择索引值,为每个其他值选择 -1。由于数组索引从零开始,我们永远不会得到 -1 作为数组最大数的索引。这意味着,在我们使用条件 index != -1
过滤我们的选择后,我们将只获得我们之前选择的最大数字的索引。
Fiddle 此处示例:https://dotnetfiddle.net/drRiVb
如果您需要与所有 linq 提供商合作(您在标题中提到的 Enumerable.Max()
而不是“Linq 的 Max()
表明您不需要,但也许您需要),那么我会建议 Enigmativity 的答案,但除非绝对需要,否则没有 ToArray()
。
如果你只关心枚举,我建议:
public static IEnumerable<int> MaxIndices(this IEnumerable<int> source)
{
using(var en = source.GetEnumerator())
{
if (!en.MoveNext())
return Enumerable.Empty<int>();
int curMax = en.Current;
List<int> indices = new List<int>{ 0 };
for (int index = 1; en.MoveNext(); ++index)
{
int current = en.Current;
if (current == curMax)
indices.Add(index);
else if (current > curMax)
{
indices.Clear();
indices.Add(index);
curMax = current;
}
}
return indices;
}
}
这通过返回一个空的可枚举开始(如果源中没有值,因此没有最大值)或者从包含 0
的列表开始作为起点始终是第一个元素是迄今为止找到的最大值。它从那个起点继续通过列表。如果给定元素与目前找到的最大值相匹配,则将其索引添加到索引列表中。如果给定元素大于目前找到的最大最小值,则它成为新的最大值,并且在添加其索引之前清除列表。否则该值将被忽略。
您可以将这两种方法与适当的重载相结合。除了以上还有:
public static IQueryable<int> MaxIndices(this IQueryable<int> source)
{
if (source is EnumerableQuery<int>)
return MaxIndices((IEnumerable<int>)source).AsQueryable(); // most efficient approach with enumerables.
return source.Select((n, i) => new { n, i })
.GroupBy(x => x.n, x => x.i)
.OrderByDescending(x => x.Key)
.FirstOrDefault() ?? Enumerable.Empty<int>().AsQueryable();
}
然后它对这两种情况都采用最有效的方法,包括将实际上可枚举的可查询对象视为可枚举对象。所有其他来源都与 Enigmativity 的回答中的一样对待。