在C#中找到两个集合的补集的最快方法

27

我有两个类型为ICollection<MyType>的集合,它们分别叫做c1c2。我想找到那些在c2中而不在c1中的项集合,其中判断是否相等的方法是基于MyTypeId属性。

在C#(3.0)中,最快的实现方式是什么?

3个回答

39

使用Enumerable.Except,并特别是接受IEqualityComparer<MyType>重载

var complement = c2.Except(c1, new MyTypeEqualityComparer());

请注意,这将产生集合差异,因此中的重复项只会在结果IEnumerable<MyType>中出现一次。在这里,您需要实现类似于IEqualityComparer<MyType>的内容。

class MyTypeEqualityComparer : IEqualityComparer<MyType> {
    public bool Equals(MyType x, MyType y) {
        return x.Id.Equals(y.Id);
    }

    public int GetHashCode(MyType obj) {
        return obj.Id.GetHashCode();
    }
}

3

如果使用C# 3.0 + Linq:

var complement = from i2 in c2
                 where c1.FirstOrDefault(i1 => i2.Id == i1.Id) == null
                 select i2;

循环遍历补集以获取项目。


2
这将使用嵌套循环,非常低效。 - Samuel Neff
也许使用 where !c1.Any(i1 => i2.Id == i1.Id) 更高效? 在这种情况下,您在 where 条件中不检索任何值,只是检查项目的存在性。请参见 DotNetFiddle - Matt

0
public class MyTypeComparer : IEqualityComparer<MyType>
{
    public MyTypeComparer()
    {    
    }

    #region IComparer<MyType> Members

    public bool Equals(MyType x, MyType y)
    {
        return string.Equals(x.Id, y.Id);
    }

    public int GetHashCode(MyType obj)
    {
        return base.GetHashCode();
    }

    #endregion     
}

然后,使用Linq:

c3 collection = new collection().add(c1);
c3.add(c2);
var items = c3.Distinct(new MyTypeComparer());

你也可以使用泛型和谓词来完成它。如果你需要一个示例,请告诉我。

1
Distinct不会过滤掉重复项,它只会让你得到c1和c2的并集,而不是c1-c2。 - luke

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接