2010-06-04 14 views
8

Po prostu kręciłem się wokół Linq i dobrze się bawiłem! Może ktoś mi pomóc z zapytaniem o to:
Mam listę danych: LINQ: Wybieranie elementów z listy (Group By/Select/Sum & Max!)

 
    Key Value 
    Aaa 12 
    AaA 10 
    AAa 5 
    BBB 2 
    Bbb 1 
1. Chcę grupować przez Key.ToUpper()
2. Dla każdej grupy muszę Max (wartość) & Sum (Value)
3. dla każdej grupy chcę wybrać wpisy tam wartość = Max (wartość)
wynik końcowy powinien wyglądać następująco:
 
    Key Max Total 
    AaA 12 27 
    AAa 12 27 
    Bbb 2 3
Dzięki!

Update, faktycznie ja też potrzebuję klucz od maksymalnej wpis:

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

+3

Brzmi podejrzanie jak zadanie domowe. –

+0

Lub pytanie do wywiadu ... praca domowa zazwyczaj nie wymaga "ToUpper" –

+0

Żadnych chaps, zobaczysz z mojego profilu, że jestem trochę przeszłości zadanie domowe :) I naprawdę nie pro koder [już], tylko dla zabawy :) –

Odpowiedz

16

:)

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 
    }; 

I trochę jak pytanie, ponieważ wszystkie małe części (niektóre są rzadko stosowane), które są wymagane, aby udzielić odpowiedzi.


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

Wykonywanie wielu agregacje na grupie jest prosta, ale wymagająca jeśli nie wiesz jak to zrobić.


select a into b 

Klauzula ta bierze wszystko, co wydarzyło się przed i rozpoczyna nowe zapytanie z celem. Bez niego musiałbym zacząć nową kwerendę tak:

var A = ... select a 

var B = from b in A 

Ważne jest, aby pamiętać, że klauzula select into usuwa kvp i g z zakresu.


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

Ten „rozpakowaniu” z kolekcji dziecięcej zamienia moje zapytanie o B-tych w zapytaniu o tych. W przeciwieństwie do domyślnego przeciążenia Enumerable.SelectMany, pozostawia zakres macierzysty (b).


where x.Value != ag.Max 

Porównując własności dziecka z majątku rodzica? Zachwycający. Ważne jest, aby pamiętać o tym, aby wydzielać where za każdym razem, gdy chcesz filtrować, nawet jeśli się zgrupowałeś (nie ma HAVING).

+0

Wowsers, szybka odpowiedź i doskonały. Dzięki! –

+0

Cieszę się, że mogłem łaskotać mniej używane części LINQ. Myślę, że ten mały dodatek sprawia, że ​​jest nieco trudniejszy? –

+0

Zaktualizowano. Niejednoznaczność wynika z tego, że wiele wierszy może mieć tę samą maksymalną wartość. Chciałbym również wspomnieć, że jeśli wszystkie wiersze dla danego klucza mają tę samą wartość, wówczas nie są zwracane żadne wiersze. –