用LINQ计算加权平均值

jsm*_*ith 20 c# linq weighted-average

我的目标是根据另一个表主键从一个表中获得加权平均值.

示例数据:

表格1

Key     WEIGHTED_AVERAGE

0200    0
Run Code Online (Sandbox Code Playgroud)

表2

ForeignKey    Length    Value
0200          105       52
0200          105       60
0200          105       54
0200          105       -1
0200          47        55
Run Code Online (Sandbox Code Playgroud)

我需要根据段的长度得到加权平均值,我需要忽略值-1.我知道如何在SQL中执行此操作,但我的目标是在LINQ中执行此操作.它在SQL中看起来像这样:

SELECT Sum(t2.Value*t2.Length)/Sum(t2.Length) AS WEIGHTED_AVERAGE
FROM Table1 t1, Table2 t2
WHERE t2.Value <> -1
AND t2.ForeignKey = t1.Key;
Run Code Online (Sandbox Code Playgroud)

我仍然是LINQ的新手,并且很难弄清楚我将如何翻译它.结果加权平均值应该大约为55.3.谢谢.

jsm*_*ith 55

我这样做足以让我为LINQ创建了一个扩展方法.

public static double WeightedAverage<T>(this IEnumerable<T> records, Func<T, double> value, Func<T, double> weight)
{
    double weightedValueSum = records.Sum(x => value(x) * weight(x));
    double weightSum = records.Sum(x => weight(x));

    if (weightSum != 0)
        return weightedValueSum / weightSum;
    else
        throw new DivideByZeroException("Your message here");
}
Run Code Online (Sandbox Code Playgroud)

获得数据子集后,调用看起来像这样.

double weightedAverage = records.WeightedAverage(x => x.Value, x => x.Length);
Run Code Online (Sandbox Code Playgroud)

这已变得非常方便,因为我可以根据同一记录中的另一个字段获得任何数据组的加权平均值.

更新

我现在检查除以零并抛出更详细的异常而不是返回0.允许用户捕获异常并根据需要处理.

  • 我必须在计算后添加"If weightedSum.AlmostZero()返回0",以防止在所有权重和/或所有值为零时除以零.AlmostZero是一个扩展函数,用于检查double是否为零. (2认同)