c# - 如何编写扩展函数以返回自定义类型的平均值?

标签 c# extension-methods average

这可能非常简单,但我的尝试(在 Intellisense 和 MSDN 的指导下)都没有成功。

如果我有一个包含 3 个 double 的类,我怎样才能得到这些列表的平均值?

class DataPoint
{
    public int time;
    public int X;
    public int Y;
    public int Z;
    // Constructor omitted
}

class Main
{
    List<DataPoint> points = new List<DataPoint>();
    // Populate list
    DataPoint averagePoint = points.Average(someMagicHere);
}

我希望 averagePoint 包含 timexyz值是构成列表的元素的这些属性的平均值。我该怎么做呢?我正在努力解决的问题是(我认为)someMagicHere,但我可能一开始就使用了完全错误的方法。

最佳答案

问题不是很清楚,但听起来你想要的是一个新点 P,其中 P.X 是列表中点的所有 X 坐标的平均值,依此类推,是吗?

解决此类问题的一般方法是将其分解:

首先将点列表转换为四个整数列表。

var times = from p in points select p.Time;
var xs = from p in points select p.X;
... and so on ..

或者,如果您更喜欢这种表示法:

var times = points.Select(p=>p.Time);

现在你可以平均这些:

double averageTime = times.Average();
double averageX = xs.Average();
... and so on ...

现在您有了四个值( double 值),您可以使用它们来构建平均点。当然,您必须使用您喜欢的任何舍入将 double 转换为整数。

但是,有一个特殊版本的“Average”,它将 Select 和 Average 合并为一个操作。你可以说

double averageTime = points.Average(p=>p.Time);

并一步完成投影和平均值。

正如一些人指出的那样,这种方法的缺点是序列被枚举了四次。这可能没什么大不了的,因为它是一个内存列表,但如果它是一个昂贵的数据库查询,则可能更重要。

另一种方法是在您的 DataPoint 类上定义加法运算符(如果通常对两点求和有意义,但它可能没有意义)。一旦有了加法运算符,对所有点求和就很简单了。

无论是否定义加法运算符,都可以使用Aggregate计算所有点的总和,然后将总和的四个字段除以点数。

DataPoint sum = points.Aggregate(
    new DataPoint(0, 0, 0, 0), 
    (agg, point)=> new DataPoint(agg.time + point.time, agg.x + point.x, ... ));

或者,如果您有运算符(operator),只需:

DataPoint sum = points.Aggregate(
    new DataPoint(0, 0, 0, 0), 
    (agg, point)=> agg + point);

现在您有了总和,因此计算平均值很简单。

关于c# - 如何编写扩展函数以返回自定义类型的平均值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6298763/

相关文章:

c# - 提交试用版WP7应用

swift - 如何从同一 ViewController 的扩展访问 var

mysql - 所有项目的 5 天移动平均线

javascript - 如何对数组中高于阈值的元素进行平均?

c# - 理解代码

c# - 从 IIS 站点绑定(bind)中删除 IP

c# - C#设置加载和保存

c# - 将 C# 链接起来看起来像 jQuery 是一个好主意吗?

.net - Paramarrays 的通用 Concat 扩展方法不适用于 IEnumerable(of String)

R 取一个变量在另一个数值变量的区间内的平均值