2013-08-21 320 views
2

我有一些代碼,我寫了下面這個基本模式。我期待看看是否有更好,更簡潔或更好的表現方式來實現其目標。目標是將一個列表中的項目與另一個列表中的項目進行比較,如果匹配則執行操作。我得到它的唯一方法是工作,下面的想法,但我是新來的C#和.NET,我不知道是否有更好的方法。嵌套while循環替代

list A 
list B 
int counter; 
int counter2; 
while (counter < comparison item) 
{ 
    while (counter2 < comparison item 2) 
    { 
     if (A[counter] == B[counter2]) 
     { 
      // do stuff 
     } 
     counter2++; 
    } 
    counter++; 
} 
+0

LINQ是一種可能性,但它在功能上是相同的東西。 – siride

+0

您也可以事先對列表進行排序,並執行合併連接類型操作。根據列表的大小和你計劃在做什麼樣的操作,它可能會更快。一如既往,衡量。 – siride

回答

3

這個雙循環結構很簡單,但它不是高性能的。問題是比較的數量:如果第一組有N項目,第二組有M,那麼將會有N*M比較。每套有1,000件商品,我們正在談論1,000,000個比較。

更好的方法是散列第一組的項目,然後在第二組中搜索散列項目。由於散列在固定的時間裏完成,你可以在M+N操作做到這一點,或者兩套各1,000個項目約2000:

var setA = new HashSet<int>(listA); 
foreach (var b in listB) { 
    if (setA.Contains(b)) { 
     ... 
    } 
} 

LINQ庫讓您的代碼甚至更少行做到這一點:

foreach (var ab in listA.Intersect(listB)) { 
    ... 
} 
+0

謝謝你的答案,對於第二個例子,你會使用列表作爲List對象還是HashSet對象? – wondergoat77

+0

@ wondergoat77無論你傳遞給LINQ的容器如何:它在內部使用一個基於散列的容器來進行合併,將輸入視爲「IEnumerable '。 – dasblinkenlight

+0

真棒,謝謝你的提示! – wondergoat77

1

如果不需要改變清單那麼你應該使用一個foreach循環。

foreach (var itemA in A) 
{ 
    foreach (var itemB in B) 
    { 
     if (itemA == itemB) {} 
    } 
} 

如果確實需要更改列表那麼你應該使用一個for循環。

for (var i = 0; i < A.Count; i++) 
{ 
    for (var j = 0; j < B.Count; j++) 
    { 
     if (A[i] == B[j]) {} 
    } 
} 

如果兩個列表進行排序你可以以通過列表會更有效地做到這一點。

int i = 0; 
int j = 0; 

while (A.Length <= i && B.Length <= j) 
{ 
    if (A[i] == B[j]) 
    { 
     // items are equal 
     i++; 
     j++; 
    } 
    else if (A[i] > B[j]) // Comparison of the ordered value, could be a property on the item. 
    { 
     j++; // increment B's counter 
    } 
    else 
    { 
     i++; // increment A's counter 
    } 
}