获得Linq中元素出现次数的最大值

本文关键字:最大值 Linq 元素 获得 | 更新日期: 2023-09-27 18:07:11

大家好,我有两个类,我将其命名为A和B

A是一个列表,每个A元素都有一个B元素的列表。元素的类型为

我想通过在B元素列表中出现来得到一个B元素

var listB = A
  .SelectMany(a => a.B);
var listBId = listB
  .Where(b => b.Type == SelectedType)
  .Select(b => b.Id);
var IdMaxoccur = listBId
  .GroupBy(x => x)
  .OrderByDescending(x => x.Count())
  .First()
  .Key;

我发现这有点重,只是得到一个id的最大出现在一个列表....你知道更好的方法吗?

获得Linq中元素出现次数的最大值

我认为你的代码是足够好的,如果你重写和简化它一点和处理情况,当你的列表是空的。这段代码假设0不是一个有效的Id。

var result = A
    .SelectMany(x => x.B)
    .Where(x => x.Type == selectedType)
    .GroupBy(x => x.Id, new { Id = x.Key, Count = x.Count() })
    .OrderByDescending(x => x.Count)
    .FirstOrDefault();
Console.WriteLine("Max ID = {0}, Count = {1}", result.Id, result.Count);

如果你仍然认为你现有的代码太复杂,你可以写一个扩展方法来隐藏复杂性

public static int TryGetBIdWithMaxOccur(this IEnumerable<A> input, SelectedTypeEnum selectedType)
{
    var result = input
        .SelectMany(x => x.B)
        .Where(x => x.Type == selectedType)
        .GroupBy(x => x.Id, new { Id = x.Key, Count = x.Count() })
        .OrderByDescending(x => x.Count)
        .Select(x => x.Id)
        .FirstOrDefault();
    return result;
}

那么你可以这样使用:

var result = A.TryGetBIdWithMaxOccur(SelectedTypeEnum.CoolValue);
if(result != default(int))
{
    //do stuff
}

只是一个想法

var bs = A.SelectMany().Where().Select(b=>b.Id).OrderBy();
int current = -1, maxB = -1;   // make sure it is stub Id
int currentCount = 0, maxCount = 0;
foreach(var b in bs)
{
    if (b != current)
    {
         // check if previous was max
         if (currentCount > maxCount)
         {
              maxB = current;
              maxCount = currentCount;
         }
         // change current
         current = b;
         currentCount = 0;
    }
    currentCount ++;
}

为了使其更短,您可以将Where选择器放在SelectMany中,并使用GroupBy过载:

var idMaxOccur = A
    .SelectMany(a => a.B.Where(b => b.Type == selectedType))
    .GroupBy(b => b.Id, b => b.Id)
    .OrderByDescending(g => g.Count())
    .First().Key;