2011-03-25 139 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