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 的回答中的一样对待。