LINQ: Выбор объектов из списка (Group By/Select/Sum & Max!)

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

    Key  Value
    Aaa  12
    AaA  10
    AAa  5
    BBB  2
    Bbb  1
1. Я хочу сгруппироваться Ключом. ToUpper ()
2. Для каждой группы мне нужен Max (Значение) и Сумма (Значение)
3. Для каждой группы я хочу выбрать записи Там Значение! = Max (значение)
конечный результат должен быть похожим на это:
    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 
9
задан Andrew White 4 June 2010 в 01:38
поделиться

1 ответ

:)

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's в запрос о a's. В отличие от стандартной перегрузки Enumerable.SelectMany, она оставляет родителя (b) в области видимости.


where x.Value != ag.Max

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

16
ответ дан 4 December 2019 в 12:59
поделиться
Другие вопросы по тегам:

Похожие вопросы: