Просто получив мою голову вокруг Linq и имея большую забаву! Может любой помогать мне с запросом для этого:
У меня есть список данных:
Key Value Aaa 12 AaA 10 AAa 5 BBB 2 Bbb 11. Я хочу сгруппироваться Ключом. ToUpper ()
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
:)
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
).