2011-03-25 185 views
1

我有一個比較泛型集合?

ObservableCollection<BasicClass> allCollection; 
ObservableCollection<BasicClass> selectedCollection; 

其中

BasicClass 
{ 
public Name {get;set;} 
public Age {get;set;} 
} 

現在我加入了很多BasicClass項目allCollection,只選擇BasicClassselectedCollection

地方我想添加物品selectedCollection其中不存在在allCollection。 我想這

foreach(var a in allCollection) 
    { 
      foreach(var s in selectedCollection) 
      if(a.Name!=s.Name) 
       //selectedCollection.Add(new BasicClass {Name =a.Name, Age=a.Age}); 
    } 

但問題是,這個代碼是增加新的BasicClass爲每一個無與倫比的名字, 但我實際工作的要求是,對於allCollection的每名比較所有selectedCollection項目。如果它不存在,那麼添加其他的移動到下一個項目。

LINQ解決方案可以幫助嗎?實際上,我通過更多if和flags實現了這一目標,但這看起來很緊張。 我的傳統解決方案

foreach(var a in allCollection) 
     { 
      bool same = false; 
      foreach(var s in selectedCollection) 
      if(a.Name==s.Name) 
       same=true; 
     } 
    if(same==false) 
    selectedCollection.Add(new BasicClass {Name =a.Name, Age=a.Age}); 

而且我討厭這個..

編輯:

我不想比較集合集合。 我想比較collection1價值collection2所有的值,如果不是有那麼我想補充

+0

_「我的實際工作的要求是,對於allCollection的每名比較所有selectedCollection項目如果它不存在再加入否則移動到下一個項目。「_ - 這是對過程的描述,而不是要求。 – stakx 2011-03-25 12:37:28

+1

常規名稱比較使密鑰非常糟糕。例如,真實世界的數據通常會有同名的人。你期望如何處理這些情況? – asawyer 2011-03-25 12:39:22

+0

@asawyer這不是一個實際的問題或塞納里奧......我給了一個簡單的例子,可以匹配我的問題。 – PawanS 2011-03-25 13:32:18

回答

1

你確定你不只是需要這個嗎?

 foreach(var a in allCollection)  
     {  
      if (!selectedCollection.Contains(a)) 
       selectedCollection.Add(new BasicClass {Name =a.Name, Age=a.Age});  
     } 

編輯

我剛看到低於約只在名稱匹配您的評論,所以上面的是不是真的,你想要的東西:)。試試這個辦法來代替:

 foreach(var a in allCollection) 
     { 
      if (!selectedCollection.Any(s => a.Name == s.Name)) 
      { 
       selectedCollection.Add(new BasicClass {Name =a.Name, Age=a.Age});  
      } 
     } 

編輯

正如克里斯建議你也可以使用「除」創建集合。我不確定這會獲得多少收益,但它可能會更快,但它涉及編寫比較器代碼並創建一個新的臨時集合。但是,它非常簡潔,例如你曾經有過的comparaer寫你只需給你的缺項添加到集合:

selectedCollection.Concat(allCollection.Except(selectedCollection)); 
+0

問題在於它的運行時間爲O(n^2),而我相信基於Linq的解決方案是O(n),因爲它們正在使用哈希表進行設置操作。 – 2011-03-25 13:37:23

+0

這個工作,簡短甜蜜,但如果我們不考慮O(n^2),我會嘗試使它在LINQ – PawanS 2011-03-25 13:50:33

+0

你可以看看克里斯建議的「Except」appraoch。我懷疑它會產生巨大的差異,但我會在我的答案中添加一些代碼。 – 2011-03-25 14:13:28

1

我不知道我理解正確你的要求,所以我可能會錯過了點...

BasicClass應該實現IEquatable<BasicClass>接口,這樣的BasicClass兩個實例可以爲比較相等:

class BasicClass : IEquatable<BasicClass> 
{ 
    public Name {get;set;} 
    public Age {get;set;} 

    public bool Equals(BasicClass other) 
    { 
     if (other == null) 
      return false; 
     return string.Equals(this.Name, other.Name); 
    } 

    public override int GetHashCode() 
    { 
     return Name == null ? 0 : Name.GetHashCode(); 
    } 
} 

現在你可以使用Except方法發現在allCollection項目,但不selectedCollection

BasicClass[] notSelected = allCollection.Except(selectedCollection).ToArray(); 
foreach(BasicClass item in notSelected) 
{ 
    selectedCollection.Add(item); 
} 

或者,你可以實現一個IEqualityComparer<BasicClass>並將它傳遞給Except(而不是實施IEquatable<BasicClass>BasicClass

+0

'GetHashCode'也應在示例中定義。 – 2011-03-25 12:47:48

+0

@克里斯,是的,你是對的......修好了,謝謝! – 2011-03-25 13:28:20

0

你說得對,這是更容易使用LINQ實現:

var itemsToAdd = allCollection.Except(selectedCollection); 
foreach (var item in itemsToAdd) 
    selectedCollection.Add(item); 

另一方面,這只是讓這兩個列表包含完全相同的項目。當然,這是你想要的?

如果BasicItem重寫基於Name的「Equals」和「GetHashCode」,那麼這就是您所需要的。如果沒有,那麼你也將需要實現一個IEqualityComparer

//Allows us to compare BasicItems as if Name is the key 
class NameComparer: IEqualityComparer<BasicItem> 
{ 
    public bool Equals(BasicItem first, BasicItem second) 
    { 
     return first.Name == second.Name; 
    } 

    public int GetHashCode(BasicItem value) 
    { 
     return value.Name.GetHashCode; 
    } 
} 

你現在把這個類的一個實例來Except

var itemsToAdd = allCollections.Except(selectedCollection, new NameComparer()); 
+0

我只想比較姓名而不是年齡。如果名稱相同,但Age不爲 – PawanS 2011-03-25 12:44:23

+0

@Gaps與Thomas顯示的類似,您需要覆蓋'Equals'和'GetHashCode'以僅在比較中使用Name。如果這不是你一直想要的行爲,那麼你必須實現和IQualityComparer。我會添加一些代碼。 – 2011-03-25 12:47:16

1

所以基本上你需要一個「,其中,不-在'? Linq->除了要走的路,在BasicClass.name上過濾只會實現IEqualityComparer。

+0

你是正確的,但它不能解決我的問題。 – PawanS 2011-03-25 13:33:41