2015-08-10 3 views
0

Привет всем У меня есть 2-го класса для примера я буду называть его А и ВПолучить Макс вхождение элемента в Linq

А список и каждый Элемент есть список 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; 

Я нахожу это немного тяжелым для просто получить максимальное вхождение идентификатора в списке .... Вы знаете лучший способ сделать это?

+4

Так как рабочий код, который вы хотите улучшить, ваш вопрос лучше подходит для [codereview.se]. –

+0

Не знал, что это существует ... Я часто не использую переполнение стека: P – Jebik

+2

Если вы используете [метод расширения 'MaxBy() для linq] (https://www.nuget.org/packages/MoreLinq .Source.MoreEnumerable.MaxBy /), вы можете написать это по строкам: 'var result = A.OfType (SelectedType) .MaxBy (x => x.Id) .Key;' (несколько упрощенное от того, что вы на самом деле необходимость). –

ответ

1

Я думаю, что ваш код достаточно хорошо, если вы переписать и упростите это бит и обработайте регистр, когда ваш список пуст. Этот код предполагает, что 0 не является допустимым идентификатором.

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

Это неверно, так как он вернет идентификатор с наименьшими вхождениями. –

+0

@ KasparsOzols - Спасибо, отредактирован –

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 ++; 
} 
Смежные вопросы