在一个LINQ查询中获取两列的总和

假设我有一个名为Items的表(ID int,Done int,Total int)

我可以做两个查询:

int total = m.Items.Sum(p=>p.Total) int done = m.Items.Sum(p=>p.Done) 

但是我想在一个查询中这样做:

 var x = from p in m.Items select new { Sum(p.Total), Sum(p.Done)}; 

当然有一种方法可以从LINQ语法中调用聚合函数…?

这将做的伎俩:

 from p in m.Items group p by 1 into g select new { SumTotal = g.Sum(x => x.Total), SumDone = g.Sum(x => x.Done) }; 

总结表,按常数分组:

 from p in m.Items group p by 1 into g select new { SumTotal = g.Sum(x => x.Total), SumDone = g.Sum(x => x.Done) } 

怎么样

  m.Items.Select(item => new { Total = item.Total, Done = item.Done }) .Aggregate((t1, t2) => new { Total = t1.Total + t2.Total, Done = t1.Done + t2.Done }); 

弄清楚在哪里提取总额或其他集合在我的代码的其余部分混淆了我,直到我记得我构build的variables是一个Iqueryable。 假设我们的数据库中有一张由订单组成的表格,我们想为ABC公司制作一份摘要:

 var myResult = from g in dbcontext.Ordertable group p by (p.CUSTNAME == "ABC") into q // ie, all of ABC company at once select new { tempPrice = q.Sum( x => (x.PRICE ?? 0m) ), // (?? makes sure we don't get back a nullable) tempQty = q.Sum( x => (x.QTY ?? 0m) ) }; 

现在有趣的部分 – tempPrice和tempQty没有在任何地方声明,但他们必须是myResult的一部分,不是吗? 访问它们如下:

 Console.Writeline(string.Format("You ordered {0} for a total price of {1:C}", myResult.Single().tempQty, myResult.Single().tempPrice )); 

其他一些Queryable方法也可以使用。

有了一个辅助元组类,无论是你自己的还是在.NET 4中,你都可以这样做:

 var init = Tuple.Create(0, 0); var res = m.Items.Aggregate(init, (t,v) => Tuple.Create(t.Item1 + v.Total, t.Item2 + v.Done)); 

res.Item1Done列的Total列和res.Item2Total

 //Calculate the total in list field values //Use the header file: Using System.Linq; int i = Total.Sum(G => G.First); //By using LINQ to calculate the total in a list field, var T = (from t in Total group t by Total into g select g.Sum(t => t.First)).ToList(); //Here Total is a List and First is the one of the integer field in list(Total) 

这已经被回答了,但其他答案仍然会对集合进行多次迭代(多次调用Sum),或者创build大量的中间对象/元组,这可能是正确的,但是如果不是,那么您可以创build一个扩展方法(或多个),这是老式的方式,但很适合LINQexpression式。

这样的扩展方法看起来像这样:

 public static Tuple<int, int> Sum<T>(this IEnumerable<T> collection, Func<T, int> selector1, Func<T, int> selector2) { int a = 0; int b = 0; foreach(var i in collection) { a += selector1(i); b += selector2(i); } return Tuple.Create(a, b); } 

你可以像这样使用它:

 public class Stuff { public int X; public int Y; } //... var stuffs = new List<Stuff>() { new Stuff { X = 1, Y = 10 }, new Stuff { X = 1, Y = 10 } }; var sums = stuffs.Sum(s => sX, s => sY); 

当你使用Linq的创build一个新的项目集合,所以你有两个项目集合。

这是两个问题的解决scheme:

  1. 在一次迭代中总结任意数量的成员
  2. 避免重复您的项目的集合

码:

 public static class LinqExtensions { /// <summary> /// Computes the sum of the sequence of System.Double values that are obtained /// by invoking one or more transform functions on each element of the input sequence. /// </summary> /// <param name="source">A sequence of values that are used to calculate a sum.</param> /// <param name="selectors">The transform functions to apply to each element.</param> public static double[] SumMany<TSource>(this IEnumerable<TSource> source, params Func<TSource, double>[] selectors) { if (selectors.Length == 0) { return null; } else { double[] result = new double[selectors.Length]; foreach (var item in source) { for (int i = 0; i < selectors.Length; i++) { result[i] += selectors[i](item); } } return result; } } /// <summary> /// Computes the sum of the sequence of System.Decimal values that are obtained /// by invoking one or more transform functions on each element of the input sequence. /// </summary> /// <param name="source">A sequence of values that are used to calculate a sum.</param> /// <param name="selectors">The transform functions to apply to each element.</param> public static double?[] SumMany<TSource>(this IEnumerable<TSource> source, params Func<TSource, double?>[] selectors) { if (selectors.Length == 0) { return null; } else { double?[] result = new double?[selectors.Length]; for (int i = 0; i < selectors.Length; i++) { result[i] = 0; } foreach (var item in source) { for (int i = 0; i < selectors.Length; i++) { double? value = selectors[i](item); if (value != null) { result[i] += value; } } } return result; } } } 

以下是你必须做的总结:

 double[] result = m.Items.SumMany(p => p.Total, q => q.Done); 

这是一个通用的例子:

 struct MyStruct { public double x; public double y; } MyStruct[] ms = new MyStruct[2]; ms[0] = new MyStruct() { x = 3, y = 5 }; ms[1] = new MyStruct() { x = 4, y = 6 }; // sum both x and y members in one iteration without duplicating the array "ms" by GROUPing it double[] result = ms.SumMany(a => ax, b => by); 

如你看到的

 result[0] = 7 result[1] = 11