2009-07-08 1 views
0

Рассмотрим следующую иерархию классов:LINQ - Выберите правильные значения из вложенной коллекции

public class Foo 
{ 
public string Name { get; set; } 
public int Value { get; set; } 
} 
public class Bar 
{ 
public string Name { get; set; } 
public IEnumerable<Foo> TheFoo { get; set; } 
} 

public class Host 
{ 
    public void Go() 
    { 
    IEnumerable<Bar> allBar = //Build up some large list 
    //Get Dictionary<Bar, Foo> with max foo value 
    } 
} 

То, что я хотел бы сделать с помощью Linq2Objects должен получить KeyValuePair, где для каждого бара в коллекции allBBar мы выбираем Foo с значение максимального значения. Можно ли это сделать легко в одном заявлении LINQ?

ответ

2

Конечно, хотя мое предпочтительное решение использует MaxBy от MoreLINQ:

var query = allBar.ToDictionary(x => x, // Key 
           x => x.TheFoo.MaxBy(f => f.Value)); 

Обратите внимание, что это будет продолжаться грушевидный, если TheFoo пусто для любого Bar экземпляра.

+0

И без опции MaxBy? –

+1

Тогда вы в принципе захотите написать свою собственную реализацию MaxBy :) Вы * можете * сделать что-то ужасное, но было бы очень аккуратно просто включить MaxBy в ваш код. –

+0

Достаточно честный. ;) –

0

Просто добавьте комментарий Джона о MaxBy, который будет выглядеть грушеобразно, если у вас нет foos, вы можете сделать OrderByDescending, а затем использовать FirstOrDefault, чтобы получить элемент Max. Если коллекция пуста, она просто вернет null вместо того, чтобы идти «грушевидная».

var foobars = bars.ToDictionary(bar => bar, 
           bar => bar.TheFoo.OrderByDescending(foo => foo.Value).FirstOrDefault()); 

Я не думаю, что это не будет столь же эффективным, как MaxBy, но было бы более устойчивым в случае пустой коллекции.

1

Другой способ с использованием Aggregate вместо OrderBy таким образом, чтобы выяснить максимальный Foo является O (N) вместо O (п § п):

var query = allBar.ToDictionary(
    bar => bar, 
    bar => bar.TheFoo.Aggregate(
     null, 
     (max, foo) => (max == null || foo.Value > max.Value) ? foo : max)); 

 Смежные вопросы

  • Нет связанных вопросов^_^