【问题标题】:LINQ compound aggregationLINQ 复合聚合
【发布时间】:2011-07-31 15:51:33
【问题描述】:

我有一个简单的 LINQ 问题:

我有一组 FooBar。 Foobar 具有 foo 属性和 bar 属性。 我想聚合 foo 和 bar 而不会多次运行我的 foobars 集合。

即。我想要类似于 SQL 的东西:

SELECT SUM(Foo), SUM(Bar) From FooBars

int fooSum, barSum;
foreach (var foobar in foobars)
{
   fooSum += foobar.Foo;
   barSum += foobar.Bar;
}

有没有一种优雅的方式可以在 LINQ 中使用复合选择(或类似方法)来编写它?

【问题讨论】:

    标签: c# linq


    【解决方案1】:

    您可以使用Aggregate,将运行总计保存在匿名类型或元组中。虽然我自己可能只会使用普通的foreach 循环。

    var result = foobars.Aggregate(new { FooSum = 0, BarSum = 0 },
                                   (a, x) => new {
                                                     FooSum = a.FooSum + x.Foo,
                                                     BarSum = a.BarSum + x.Bar
                                                 });
    
    Console.WriteLine("FooSum=" + result.FooSum + ", BarSum=" + result.BarSum);
    

    【讨论】:

    • 正是我想要的。谢谢。
    • @LukeH:当foobars 包含很多元素时,它会不会产生很大的对象开销,因为您正在为每次迭代创建一个匿名类型的新实例?
    • @Daniel:是的,确实如此,如果您也使用Tuple<int,int> 之类的东西,同样适用,因为它们也是 ref 类型。我想您可以创建一个自定义结构来完成这项工作,或者(错误地)使用内置结构,例如KeyValuePair<int,int>。我想你也可以使用像 int[2] 这样的东西作为累加器,并在每次迭代时对其进行变异。有了这些建议,它变得真的很难看,foreach 循环绝对是更好的选择。
    • @LukeH:看看我的解决方案。它有同样的问题吗?恕我直言,不是,因为我正在重用那个匿名类型。关于丑陋:它已经是...... :-D
    • @Daniel:我认为您的版本不会编译。 Anon 类型是不可变的。
    猜你喜欢
    • 1970-01-01
    • 2015-10-29
    • 1970-01-01
    • 2010-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-09
    • 1970-01-01
    相关资源
    最近更新 更多