2012-03-16 21 views
10

Na przykład, jak mogę pogrupować następujące rekordy według GroupId używając LINQ i zsumować wszystkie pozostałe kolumny w każdej grupie? (A zatem połączenie wszystkich wierszy, w każdej grupie do jednego)Jak scalić/podsumować rekordy według grupy za pomocą LINQ?

var list = new List<Foo>() 
{ 
    new Foo() { GroupId = 0, ValueA = 10, ValueB = 100 }, 
    new Foo() { GroupId = 1, ValueA = 30, ValueB = 700 }, 
    new Foo() { GroupId = 1, ValueA = 40, ValueB = 500 }, 
    new Foo() { GroupId = 2, ValueA = 80, ValueB = 300 }, 
    new Foo() { GroupId = 2, ValueA = 20, ValueB = 200 }, 
    new Foo() { GroupId = 2, ValueA = 20, ValueB = 200 } 
}; 

Oczekiwany wynik to:

| GroupId | ValueA | ValueB | 
|---------|--------|--------| 
| 0 | 10 | 100 | 
| 1 | 70 | 1200 | 
| 2 | 120 | 700 | 

Odpowiedz

13
list.GroupBy(i => i.GroupId) 
    .Select(g => new { GroupId = g.Key, 
         ValueA = g.Sum(i => i.ValueA), 
         ValueB = g.Sum(i => i.ValueB)}); 

lub po prostu dla zabawy, można to zrobić w ciągu jednego GroupBy rozmowy używając jego przeciążeniem:

list.GroupBy(i => i.GroupId, 
     (key, groupedItems) => new { 
             GroupId = key, 
             ValueA = groupedItems.Sum(i => i.ValueA), 
             ValueB = groupedItems.Sum(i => i.ValueB), 
            }); 

lub użyć Aggregate uniknąć iteracji każda grupa wielokrotnie:

list.GroupBy(i => i.GroupId) 
    .Select(g => g.Aggregate((i1, i2) => new Foo{ GroupId = i1.GroupId, 
                ValueA = i1.ValueA + i2.ValueA, 
                ValueB = i1.ValueB + i2.ValueB, 
               })); 
3

Zastosowanie GroupBy zbierać Foo s na grupy w oparciu o ich GroupId, a następnie utworzenie nowego obiektu dla każdego "rząd" wyniku (obiekt ten może być sam w sobie oparty na podanym kodzie, ale równie dobrze mógłby być czymkolwiek innym, w tym typem anonimowym). W tym momencie zsumujesz także inne wartości.

var sums = list.GroupBy(f => f.GroupId) 
       .Select(g => new Foo 
       { 
        GroupId = g.Key, 
        ValueA = g.Sum(f => f.ValueA), 
        ValueB = g.Sum(f => f.ValueB) 
       }).ToList(); 
5
var query = list.GroupBy(x=> x.GroupId) 
       .Select(g=> new 
        { 
        GroupId = g.Key, 
        ValueA = g.Sum(x => x.ValueA), 
        ValueB = g.Sum(x => x.ValueB) 
        }); 
0

Unikanie wyrażeń lambda (prawie) i za pomocą „czysto” LINQ sposób:

var sums = from foo in list 
    group foo by foo.GroupId into groupings 
    orderby groupings.Key ascending 
    select new 
    { 
     GroupId = groupings.Key, 
     ValueA = groupings.Sum(g => g.ValueA), 
     ValueB = groupings.Sum(g => g.ValueB) 
    }; 

Myślę LINQ jest nieco bardziej naturalny język patrząc w porównaniu do lambda (nie, że nie ma nic złego. ..)

Powiązane problemy