LINQ - Выберите правильные значения из вложенной коллекции - PullRequest
0 голосов
/ 09 июля 2009

Рассмотрим следующую иерархию классов:

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?

Ответы [ 3 ]

2 голосов
/ 09 июля 2009

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

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

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

1 голос
/ 10 июля 2009

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

var query = allBar.ToDictionary(
    bar => bar,
    bar => bar.TheFoo.Aggregate(
        null,
        (max, foo) => (max == null || foo.Value > max.Value) ? foo : max));
0 голосов
/ 09 июля 2009

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

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

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

...