2012-04-18 25 views
3

假設我們有一些共同的特性,這些業務對象:性能問題迭代在C#泛型列表時

public class A 
{ 
    // Properties in common 
    public int Common { get; set; } 
    public string aValue { get; set; } 
    // Some other goes here. 
} 

public class B 
{ 
    // Properties in common 
    public int Common { get; set; } 
    public string bValue { get; set; } 

    // Some other goes here. 
} 

而且在我們的業務邏輯,我們有兩個列表像這樣的:

List<A> aList = new List<A>(); 
List<B> bList = new List<B>(); 

(並且假設我們有這些列表,每個列表至少填充100個實例) 好吧,讓我們從我們的問題開始,我們需要遍歷aList以設置bList中每個實例的一個屬性,當然匹配與財產共同的,像th是:

foreach (A a in aList) 
{ 
    B b = bList.Find(x => x.Common == a.Common); 
    if (b != null) 
     b.bValue = a.aValue; 
} 

有誰知道一個更好的方法來改善這種操作,因爲它是導致我們的應用程序需要太多的時間來完成?

感謝,

+1

我不認爲100元可引起任何性能問題。那裏有多少? – gdoron 2012-04-18 00:39:26

+1

@gdoron這取決於你多久調用一次這個功能:) – dasblinkenlight 2012-04-18 00:43:57

+0

@gdoron我想我忘了提到該應用是用於Windows Mobile設備的,所以該應用受到移動設備資源的限制。 – sammiiuu 2012-04-18 00:45:37

回答

4

由於列表中的Find是線性的,因此表現不佳。得到的算法是O(n^2)

您應該從公共屬性上的bList製作Dictionary,並通過密鑰查找,而不是使用Find進行搜索;字典查找是O(1)分期付款,因此它會使您的算法在列表長度上呈線性。

var dict = bList.ToDictionary(b => b.Common); 
foreach (A a in aList) { 
    B b; 
    if (dict.TryGetValue(a.Common, out b) { 
     b.bValue = a.aValue; 
    } 
} 
+0

很好的答案,包括大O:D – 2012-04-18 00:44:13

+0

難道不就是'B b = dict [a.Common];如果(b!= null){b.bValue = a.aValue;}' – gdoron 2012-04-18 00:47:20

+0

@gdoron不幸的是,如果該項不存在,那麼'[]'操作符將會失敗。 'TryGetValue'比'Contains + []'更直截了當,因爲它可以讓你避免按鍵進行額外的查找。 – dasblinkenlight 2012-04-18 00:53:15

1

與普通的bList複製到字典型容器作爲關鍵和使用,而不是bList本身在循環。

2

爲了高效地查看一個值,給定某個鍵不會使用列表,而是使用字典。要找到一個列表中的特定項目需要O(N),在一個字典中需要O(1)。

Dictionary<int, B> bDict = new Dictionary<int, B>(); 
foreach (B b in bList) bDict.Add(b.Common, b); 

foreach (A a in aList) { 
    if (bDict.ContainsKey(a.Common)) 
    bDict[a.Common].bValue = a.aValue; 
} 
1

我相信,如果你做一個在LINQ加入它會做一個散列連接你上兩個列表這將節省您手動創建字典在其他答案建議。我沒有工作室在這臺機器上鞭打你的樣品,稍後會嘗試更新。

如果項目數量非常少,Linq甚至可能足夠聰明,無法啓動散列連接。

編輯: 給像這樣旋轉:

var joined = from a in aList 
        join b in bList on a.Common equals b.Common 
        select new { 
          A = a, 
          B = b 
        }; 

      foreach (var item in joined) 
      { 
        item.B.bValue = item.A.aValue; 
      } 
+0

http://ideone.com/KvdvX – 2012-04-18 01:18:59

+0

+1這是我會給出的答案。使用連接還可以避免使用TryGetValue或其他方法處理源列表中的不匹配項。 – phoog 2012-04-18 04:19:26