Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/324.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 比较通用集合?_C#_Linq_Collections - Fatal编程技术网

C# 比较通用集合?

C# 比较通用集合?,c#,linq,collections,C#,Linq,Collections,我有一个 ObservableCollection<BasicClass> allCollection; ObservableCollection<BasicClass> selectedCollection; 现在,我在allCollection中添加了许多BasicClass项目,并且只在selectedCollection中选择了BasicClass 我想在selectedCollection中添加allCollection中没有的项目。 我试过这个 forea

我有一个

ObservableCollection<BasicClass> allCollection;
ObservableCollection<BasicClass> selectedCollection;
现在,我在
allCollection
中添加了许多
BasicClass
项目,并且只在
selectedCollection中选择了
BasicClass

我想在
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项。如果没有,则为下一个项目添加else move。

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所有值,如果没有,那么我想添加

我不确定我是否正确理解了您的要求,因此我可能没有抓住要点

您的
BasicClass
应该实现
IEquatable
接口,这样就可以比较
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();
    }
}

或者,您可以实现一个
IEqualityComparer
并将其传递给
(而不是在
BasicClass
中实现
IEquatable

您是对的,使用Linq更容易实现:

var itemsToAdd = allCollection.Except(selectedCollection);
foreach (var item in itemsToAdd)
    selectedCollection.Add(item);
另一方面,这将使两个列表包含完全相同的项。这是你想要的吗

如果BasicItem根据名称重写'Equals'和'GetHashCode',那么这就是您所需要的。如果没有,那么您还需要实现:


所以基本上你需要一个“where not in”?Linq->Except是在BasicClass.name上进行筛选的方法。只为Except实现IEqualityComparer。

您确定不需要它吗

        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});     
            }
        }
编辑

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

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

“我的实际要求是,对于allCollection的每个名称,比较所有选定的集合项。如果没有,则为下一项添加else move。”--这是对过程的描述,而不是要求。常规名称比较会产生非常糟糕的键。例如,现实世界的数据通常会有同名的人。你希望如何处理这些情况?@asawyer这不是一个实际问题或senario。。。我只举了一个与我的问题相匹配的简单例子。好吧,我想我应该提一下,因为我在生产环境中遇到了类似的情况,这造成了各种各样的痛苦。我只想比较一下名字而不是年龄。如果姓名相同但年龄相同,会发生什么not@Gaps与Thomas所展示的类似,您需要重写“Equals”和“GetHashCode”,以便在比较中只使用Name。如果这不是您一直想要的行为,那么您必须实现和IQualityComparer。我将添加一些代码。“GetHashCode”也应该在示例中定义。问题是它的运行时为O(n^2),而我认为基于Linq的解决方案是O(n),因为它们使用哈希表进行set操作。这是可行的,短n sweet,但如果我们不考虑O(n^2),我会尽量在林克,你可以看看克里斯建议的“除外”方法。我怀疑这会带来巨大的不同,但我会在我的答案中添加一些代码。
var itemsToAdd = allCollections.Except(selectedCollection, new NameComparer());
        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));