LINQ: Выбор элементов из списка (Группировка по / Выбрать / Сумма и Макс!) - PullRequest
9 голосов
/ 04 июня 2010

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

    Key  Value
    Aaa  12
    AaA  10
    AAa  5
    BBB  2
    Bbb  1
1. Я хочу сгруппировать по Key.ToUpper ()
2. Для каждой группы мне нужны Max (Value) и Sum (Value)
3. Для каждой группы я хочу выбрать записи Там Значение! = Макс (значение)
конечный результат должен быть таким:
    Key Max Total
    AaA 12  27
    AAa 12  27
    Bbb 2   3
Спасибо!

Обновление, на самом деле мне также нужен ключ от записи Максимум:

    Key Max Total Correct
    AaA 12  27    Aaa
    AAa 12  27    Aaa
    Bbb 2   3     BBB 

1 Ответ

16 голосов
/ 04 июня 2010

:)

var results =
  from kvp in source
  group kvp by kvp.Key.ToUpper() into g
  select new
  {
    Group = g,
    Max = g.Max(kvp => kvp.Value),
    Total = g.Sum(kvp => kvp.Value)
  } into ag
  from x in ag.Group  //SelectMany
  where x.Value != ag.Max
    //for the update to the question - note: possibly ambiguous
  let correct = ag.Group.Where(y => y.Value == ag.Max).First().Key
  select new
  {
    Key = x.Key,
    Max = ag.Max,
    Total = ag.Total,
    Correct = correct 
  };

Мне нравится этот вопрос, потому что все мелкие детали (некоторые редко используются) требуются для ответа.


Max = g.Max(kvp => kvp.Value),
Total = g.Sum(kvp => kvp.Value)

Выполнить несколько объединений в группе просто, но сложно, если вы не знаете, как.


select a into b

Этот пункт берет все, что произошло раньше, и начинает новый запрос с целью. Без него мне пришлось бы начать новый запрос, подобный этому:

var A = ... select a

var B = from b in A

Важно отметить, что предложение select into удаляет kvp и g из области видимости.


  from b in source
  from a in b.A  //SelectMany

Эта "распаковка" дочерней коллекции превращает мой запрос о b в запрос о a. В отличие от стандартной перегрузки Enumerable.SelectMany, родительский элемент (b) остается в области видимости.


where x.Value != ag.Max

Сравнение имущества ребенка со свойством родителя? Восхитительный. Важно помнить, что нужно выделять where в любое время, когда вы хотите отфильтровать, даже если вы только что сгруппировались (HAVING) нет.

...