我有一个List
分,我想用Linq计算剩下的距离(给定一个索引):
double remainingToEnd = Points.Skip(CurrentIndex).Aggregate((x, y) => x.DistanceTo(y));
这不编译:
无法将lambda表达式转换为预期的委托类型,因为 块中的某些返回类型不可隐式转换 到委托的返回类型
我通常使用Select扩展来解决这种情况,但这会阻止我计算之后的距离。
这可以通过使用循环轻松实现,但我想知道是否可以使用一些简单的Linq。我也想避免使用匿名类型。
点定义如下:
public class Point
{
public float X { get; set; }
public float Y { get; set; }
public float Z { get; set; }
public float DistanceTo(Point p2)
{
float x = this.X - p2.X;
float y = this.Y - p2.Y;
float z = this.Z - p2.Z;
return (float)Math.Sqrt((x * x) + (y * y) + (z * z));
}
}
答案 0 :(得分:1)
假设您要计算集合中点之间的总距离(从某个索引开始)。每一步都需要前一点。您可以通过zipping点集合获取它:
double remainingToEnd = Points.Skip(CurrentIndex)
.Zip(Points.Skip(CurrentIndex + 1), (x,y) => x.DistanceTo(y))
.Sum();
Zip将产生成对的起点和终点。结果选择器功能将选择每对点之间的距离。然后你只计算总和或距离。
您可以使用聚合来解决此任务,但您需要在每个步骤中存储最后一个点。所以你需要累加器来保持当前距离和最后一点:
var remainingToEnd = Points.Skip(CurrentIndex).Aggregate(
new { total = 0.0, x = Points.Skip(CurrentIndex).FirstOrDefault() },
(a, y) => new { total = a.total + a.x.DistanceTo(y), x = y },
a => a.total);
请记住,Skip
意味着只是按项目迭代您的序列而不做任何事情。如果你有很多积分,跳过两次可能会损害你的表现。因此,如果您有点列表和性能问题,那么简单的for循环将完成这项工作:
double remainingToEnd = 0.0;
for(int i = CurrentIndex; i < Points.Count - 1; i++)
remainingToEnd += Points[i].DistanceTo(Points[i+1]);
答案 1 :(得分:0)
试试这个:
double remainingToEnd = Points.Skip(CurrentIndex).Sum(point => point.DistanceTo(Points[Points.Findindex(p => p == point) - 1]));