2017-03-17 54 views
1

我點的List,我想計算出使用LINQ結束的剩餘距離(給出的指標):結合骨料和選擇的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)); 
    } 
} 
+1

嗨,什麼是'DistanceTo'的返回類型? – Christos

+0

對不起,這是一個雙重的 – Sturm

+0

沒有問題:)只是想要更多的信息。謝謝 – Christos

回答

1

假設你想計算的收集點之間總距離(從某個索引開始)。你需要每一步的前一點。您可以通過zipping點收集與自身得到它:

double remainingToEnd = Points.Skip(CurrentIndex) 
           .Zip(Points.Skip(CurrentIndex + 1), (x,y) => x.DistanceTo(y)) 
           .Sum(); 

郵編會產生對出發點和落腳點的。結果選擇器功能將選擇每對的點之間的距離。然後你只需計算總和或距離。


你可以用聚合來解決這個任務,但是你需要在每一步中存儲最後一個點。因此,你需要蓄能器將保持雙方目前的距離和最後一點:

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意味着僅僅通過項目迭代的序列項目沒有做任何事情。如果你有很多積分,跳過兩次會傷害你的表現。所以,如果你有個名單和性能問題,則循環簡單的將做的工作:

double remainingToEnd = 0.0; 
for(int i = CurrentIndex; i < Points.Count - 1; i++) 
    remainingToEnd += Points[i].DistanceTo(Points[i+1]); 
+0

謝謝,當你和一個簡單循環相比時,你對性能有什麼看法:'for(int i = CurrentIndex; i Sturm

+0

@簡單循環的Sturm性能總是優於LINQ性能。在內部它也使用循環,但也有一些對象創建和附加的方法調用在後臺。 LINQ爲您提供緊湊和富有表現力的代碼。除非你有高負載系統持續運行這段代碼,否則不要認爲會有巨大的性能差異 –

0

試試這個:

double remainingToEnd = Points.Skip(CurrentIndex).Sum(point => point.DistanceTo(Points[Points.Findindex(p => p == point) - 1]));