Tom*_*ght 1 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);
}
Run Code Online (Sandbox Code Playgroud)
我想averagePoint遏制time,x,y和z值是组成列表中元素的这些属性的平均值.我该怎么做呢?我正在努力的一点是(我认为)someMagicHere,但我可能完全使用错误的方法开始.
问题并不完全清楚,但听起来你想要的是一个新的点P,其中PX是列表中各点的所有X坐标的平均值,依此类推,是吗?
解决这类问题的一般方法是将其分解:
首先将点列表转换为四个整数列表.
var times = from p in points select p.Time;
var xs = from p in points select p.X;
... and so on ..
Run Code Online (Sandbox Code Playgroud)
或者,如果您更喜欢这种表示法:
var times = points.Select(p=>p.Time);
Run Code Online (Sandbox Code Playgroud)
现在你可以平均那些:
double averageTime = times.Average();
double averageX = xs.Average();
... and so on ...
Run Code Online (Sandbox Code Playgroud)
现在你有四个值 - 就像双打一样 - 可以用来构建平均点.当然,您必须使用您喜欢的任何舍入将双精度转换为整数.
但是,有一个特殊版本的"平均值",它将Select和Average组合成一个操作.你可以说
double averageTime = points.Average(p=>p.Time);
Run Code Online (Sandbox Code Playgroud)
并且一步完成投影和平均值.
正如一些人所指出的,这种方法的缺点是序列被列举四次.这可能不是什么大问题,因为它是一个内存列表,但如果它是一个昂贵的数据库查询可能会更重要.
另一种方法是在DataPoint类上定义加法运算符(如果通常将两个点相加是有意义的,它可能不是).一旦有了加法运算符,就可以直接得出所有点的总和.
无论是否定义加法运算符,都可以使用" 聚合"来计算所有点的总和,然后将总和的四个字段除以点数.
DataPoint sum = points.Aggregate(
new DataPoint(0, 0, 0, 0),
(agg, point)=> new DataPoint(agg.time + point.time, agg.x + point.x, ... ));
Run Code Online (Sandbox Code Playgroud)
或者,如果您有运营商,只需:
DataPoint sum = points.Aggregate(
new DataPoint(0, 0, 0, 0),
(agg, point)=> agg + point);
Run Code Online (Sandbox Code Playgroud)
现在你有了总和,所以计算平均值很简单.