比较泛型系列?

时间:2011-03-25 12:32:14

标签: c# linq collections

我有一个

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

,其中

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

现在我向BasicClass添加了多个allCollection项,并且只选择了BasicClassselectedCollection

SomeWhere我想在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的每个Name,比较所有selectedCollection项。如果不存在,则为下一个项目添加其他移动。

LINQ解决方案有助于此吗?实际上我通过更多的if和旗帜实现了这一点,但这看起来很忙。 我的传统解决方案

    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的所有值进行比较,如果不存在,那么我想添加

4 个答案:

答案 0 :(得分: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

答案 1 :(得分:1)

所以基本上你需要'where-not-in'? Linq-&gt;除了是要去的方法,过滤BasicClass.name只实现IEqualityComparer for Except。

答案 2 :(得分: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});     
            }
        }

修改

正如克里斯建议你也可以使用“除外”来创建一个集合。我不确定这会获得多少收益,它可能会更快,但它涉及编写比较器代码并创建一个新的临时集合。但是,它非常简洁。一旦您编写了比较器,您只需要将此缺失的项目添加到集合中:

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

答案 3 :(得分: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());