在Linq中获取Max出现的元素

时间:2015-08-10 08:59:47

标签: c# linq

大家好,我有2个例子,我将它命名为A和B

A是一个列表,每个A元素都有一个B元素列表。 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的最大出现次数.... 你知道更好的方法吗?

3 个答案:

答案 0 :(得分:1)

我认为如果你重写并简化它并且在列表为空时处理大小写,你的代码就足够了。此代码假定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
}

答案 1 :(得分:0)

为了缩短它,您可以将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;

答案 2 :(得分:0)

只是一个想法

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