Enumerable.Max()如果有两个最大值

时间:2015-10-24 23:35:37

标签: c# enumerable

我正在尝试从整数数组中获取最大值,但如果有两个值被认为是最大值,我需要在数组中找到它们的索引。

即。如果我有阵列: {10,13,13,9,8} 我需要找到13个值的索引

如果我有阵列: {10,13,12,9,8} 我需要返回13的索引

我通过使用完成了第二部分     myArray.ToList().IndexOf(myArray.Max());

但无法弄清楚第一个例子。

4 个答案:

答案 0 :(得分:1)

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();

这给出了结果:

result

记住数组是从零开始的,上面两个值是数组中13的索引。

答案 1 :(得分:1)

你可以这样做:

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过滤我们的选择后,我们只会获得之前选择的最大数字的索引。

这里的小提琴示例:https://dotnetfiddle.net/drRiVb

答案 2 :(得分:0)

试试这个:

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

答案 3 :(得分:0)

如果您需要与所有linq提供商合作(您提及Enumerable.Max()而不是标题中的“Linq's Max()表示您没有,但也许您这样做”,那么我建议使用Enigmativity's回答,但没有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的列表开始,因为起始点始终是第一个元素是到目前为止发现的最大值。从那个起点开始,它继续通过列表。如果给定元素与到目前为止找到的最大值匹配,则将其索引添加到索引列表中。如果给定元素大于到目前为止找到的maxmimum,则它将成为新的最大值,并且在添加索引之前清除列表。否则,该值将被忽略。

您可以将两种方法与适当的重载相结合。以及以上有:

  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的回答。