2012-03-16 13 views
10

Por ejemplo, ¿cómo puedo agrupar los siguientes registros en GroupId usando LINQ, y sumar todas las otras columnas en cada grupo? (Fusionando todas las filas de cada grupo en uno)¿Cómo combinar/sumar registros por grupo usando 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 } 
}; 

resultado esperado es:

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

Respuesta

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

o simplemente por diversión puede hacerlo dentro de un GroupBy llamada usando su sobrecarga:

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

o puede utilizar Aggregate para evitar la iteración cada grupo muchas veces:

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

Uso GroupBy para recoger Foo s en grupos en función de su GroupId, y luego crear un nuevo objeto para cada "fila" del resultado (ese objeto puede ser un Foo basado en el código que usted proporciona, pero podría ser cualquier otra cosa, incluso un tipo anónimo). En ese punto, también resumirá los otros valores.

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

Evitar las expresiones lambda (casi) y el uso de una forma LINQ "puramente":

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

Sólo pienso LINQ es un poco más natural del lenguaje parecido, en comparación con lambda (no es que haya nada malo en eso. ..)