如何使用LINQ按组合并/求和记录?

时间:2012-03-16 18:09:17

标签: c# linq

例如,如何使用LINQ按GroupId对以下记录进行分组,并将每个组中的所有其他列相加? (从而将每个组中的所有行合并为一个)

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

预期结果是:

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

4 个答案:

答案 0 :(得分:14)

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

或只是为了好玩,您可以使用其重载在GroupBy调用中执行此操作:

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

或者您可以使用Aggregate来避免多次迭代每个组:

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

答案 1 :(得分: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)
                  });

答案 2 :(得分:3)

使用GroupBy根据FooGroupId收集到组中,然后为结果的每个“行”创建一个新对象(该对象可以是{{ 1}}本身基于你给出的代码,但它可以很容易地成为其他任何东西,包括匿名类型)。此时,您还将总结其他值。

Foo

答案 3 :(得分:0)

避免使用lambda表达式(几乎)并使用“纯粹”LINQ方式:

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

我认为LINQ与lambda相比看起来更自然一点(并不是说有什么问题......)