使用linq计算平均值而不进行分组

时间:2013-06-07 09:10:46

标签: c# linq

我有一个数据表,包含几列。 我想用linq计算这些的平均值,而不进行分组: 我试过这个:

dtPointCollFb.GroupBy(r => 1).Select(r => new
        {
            Plus100 = r.Average(item => item.PLUS100),
            Plus50 = r.Average(item => item.PLUS50),
            Plus10 = r.Average(item => item.PLUS10),
            Plus5 = r.Average(item => item.PLUS5),
            Plus1 = r.Average(item => item.PLUS1),
            NULLA = r.Average(item => item.NULLA)
        }).ToList()

当我计算Sum时,这非常有效,但是平均值会产生第一个记录值,而不是所有记录的平均值。 我认为这是不必要的:.GroupBy(r => 1)因为我正在使用常量分组。

但是如果没有这个,我不能仅对整个查询使用平均值,而只能用于一列:

dtPointCollFb.Average(r => r.PLUS100)

那么有人可以制作一个简单的最佳实践解决方案吗? 如果可以使用方法语法,而不是查询。

我想要这样的事情:

dtPointCollFb.GroupBy(r => 0).Select(r => new
        {
            Plus100 = r.Sum(item => item.PLUS100) / dtPointCollFb.Rows.Count,
            Plus50 = r.Sum(item => item.PLUS50) / dtPointCollFb.Rows.Count,
            Plus10 = r.Sum(item => item.PLUS10) / dtPointCollFb.Rows.Count,
            Plus5 = r.Sum(item => item.PLUS5) / dtPointCollFb.Rows.Count,
            Plus1 = r.Sum(item => item.PLUS1) / dtPointCollFb.Rows.Count,
            NULLA = r.Sum(item => item.NULLA) / dtPointCollFb.Rows.Count
        }).ToList()

但更简单,更清洁。这正确地产生了平均值。

2 个答案:

答案 0 :(得分:6)

Enumerable.Average计算一系列数字的平均值。所以你需要为你需要的每个平均项目(即Select)项目。

dtPointCollFb.Select(r => r.PLUS100).Average()

dtPointCollFb.Average(r => r.PLUS100)    

GroupBy构建列表列表。在这种情况下,(外部)列表具有一个元素。 (因为你对原始列表中的所有元素都是任意使用相同的键)

所以你上面的内容可以很容易地写成:

var averages = new
{
    Plus100 = dtPointCollFb.Average(item => item.PLUS100),
    Plus50 = dtPointCollFb.Average(item => item.PLUS50),
    Plus10 = dtPointCollFb.Average(item => item.PLUS10),
    Plus5 = dtPointCollFb.Average(item => item.PLUS5),
    Plus1 = dtPointCollFb.Average(item => item.PLUS1),
    NULLA = dtPointCollFb.Average(item => item.NULLA)
};

执行更多操作需要自定义扩展功能(扩展IEnumerable<DataTableClass>)。

答案 1 :(得分:2)

如果像Christopher建议的那样,您想使用扩展程序,则可以使用Aggregate方法。

鉴于课程

public class DataPoint
{
    public double Plus100 { get; set; }
    public double Plus50 { get; set; }
    public double Plus10 { get; set; }
    public double Plus5 { get; set; }
    public double Plus1 { get; set; }
    public double NULLA { get; set; }
}

平均函数看起来像这样(手动计数避免了通过集合的多个枚举):

public static DataPoint Average(this IEnumerable<DataPoint> dataPoints)
{
    var count = 0;
    var totals = dataPoints.Aggregate((lhs, rhs) =>
        {
            ++count;
            return new DataPoint
                {
                    Plus100 = lhs.Plus100 + rhs.Plus100,
                    Plus50 = lhs.Plus50 + rhs.Plus50,
                    Plus10 = lhs.Plus10 + rhs.Plus10,
                    Plus5 = lhs.Plus5 + rhs.Plus5,
                    Plus1 = lhs.Plus1 + rhs.Plus1,
                    NULLA = lhs.NULLA + rhs.NULLA
                };
        });

    return new DataPoint
        {
            Plus100 = totals.Plus100 / count,
            Plus50 = totals.Plus50 / count,
            Plus10 = totals.Plus10 / count,
            Plus5 = totals.Plus5 / count,
            Plus1 = totals.Plus1 / count,
            NULLA = totals.NULLA / count
        };
}

这种方法的优点是它只进行一次收集。如果您有一个大型数据集,这将节省计算能力。如果您的数据点较少,我会使用克里斯托弗的方法。