2014-08-27 192 views
0

對於某些標籤元素的座標,我有2個列表(List<Point>)。移動之前的一個列表和一個列表,因此索引指向相同的標籤元素。我想比較每個具有相同索引的元素,並查看哪些元素的點發生了變化。Linq:查找具有不同值但相同索引的2列表的元素

List<int> changedIndexes = new List<int>(); 
for(int i = 0; i < labelLocationsBefore.Count; i++) 
{ 
    if (labelLocationsBefore[i].X != labelLocationsAfter[i].X || labelLocationsBefore[i].Y != labelLocationsAfter[i].Y) 
    { 
     changedIndexes.Add(i); 
    } 

} 

這是什麼循環。但我怎樣才能將它轉換成Linq表達式並檢索已更改的標籤索引?

回答

1

您正在尋找Selectthis overload方法,這需要Func<T, int, bool>其中第二個參數是指數

changedIndexes = labelLocationsBefore 
    .Select((point,idx) => new { point, idx }) 
    .Where(p => p.point.X != labelLocationsAfter[p.idx].X || 
       p.point.Y != labelLocationsAfter[p.idx].Y) 
    .Select(p => p.idx) 
    .ToList(); 
+0

我不確定這是否比Jon更好,但我更喜歡這個解決方案,因爲我覺得它更乾淨。可能.Zip會讓它變慢? – roverred 2014-08-28 00:23:42

1

一種選擇是使用Enumerable.Zip加入兩個集合,然後Select得到然後適當地過濾:

var changedIndexes = labelLocationsBefore 
    .Zip(labelLocationsAfter, (before, after) => before.Equals(after)) 
    .Select((equal, index) => new { Moved = !equal, Index = index }) 
    .Where(result => result.Moved) 
    .Select(result => result.Index) 
    .ToList(); 

這段代碼有幾個很好的屬性(它是基數d在表達式上,易於閱讀,沒有重複),但是由於需要在所有點之前/之後產生「移動的/索引」對,所以它比直的for循環更加繁瑣和性能更低 - 即使那些僅僅確定他們沒有被移動的人也足以無視他們。

相關問題