如何使用LINQ的let计算分组数据中field3>0的平均值?
修正Linq分组计算平均值的语法问题
你遇到的问题其实是Average()方法的调用方式不对——当你用Where过滤后,返回的是DataRow(或你的实体类)的集合,直接调用Average()时,编译器不知道要计算哪个属性的平均值,这和你计算包含0的平均值时明确指定g => g.field3是一个道理。
这里给你两种正确的写法,都能实现排除field3=0.0的平均值计算,并且可以通过let复用这个结果:
写法1:先过滤再选择字段计算
这种写法逻辑最直观,先筛选出field3大于0的元素,再提取field3的值,最后计算平均值:
var table3 = from d in table1sum.Concat(table2sum) group d by new { d.field1, d.field2 } into dg // 先过滤,再选择field3属性,最后计算平均值 let field3Average = dg.Where(g => g.field3 > 0.0) .Select(g => g.field3) .Average() select new { GroupField1 = dg.Key.field1, GroupField2 = dg.Key.field2, ExcludedZeroAverage = field3Average, // 可以同时保留带0的平均值,方便复用 IncludeZeroAverage = dg.Average(g => g.field3) };
写法2:利用Average忽略NaN的特性(更简洁)
Linq的Average方法会自动忽略NaN值,所以我们可以把field3=0.0的情况替换成double.NaN,这样计算时就会自动排除这些值:
var table3 = from d in table1sum.Concat(table2sum) group d by new { d.field1, d.field2 } into dg // 用三元表达式替换0为NaN,直接计算平均值 let field3Average = dg.Average(g => g.field3 > 0.0 ? g.field3 : double.NaN) select new { dg.Key.field1, dg.Key.field2, ExcludedZeroAverage = field3Average, IncludeZeroAverage = dg.Average(g => g.field3) };
额外提示:处理空分组的情况
如果某个分组里所有元素的field3都是0.0,那么写法1中的Where会返回空集合,直接调用Average()会抛出InvalidOperationException。这时候可以用DefaultIfEmpty()指定一个默认值(比如0.0)来避免报错:
let field3Average = dg.Where(g => g.field3 > 0.0) .Select(g => g.field3) .DefaultIfEmpty(0.0) // 空集合时返回0.0作为默认值 .Average()
内容的提问来源于stack exchange,提问作者Markku Rintala
相关产品推荐
相关产品推荐

