计算两组交集和差异的最佳方法是什么?

时间:2011-09-23 13:54:46

标签: c# .net list set

我有2个列表List<Class1>List<Class2>,它们由相同的属性Class1.KeyClass2.Key(字符串)进行比较,我想编写一个函数来生成3个列表他们之外

  1. List<Class1>两个列表中都有的元素
  2. List<Class1>仅出现在第一个列表中的元素
  3. List<Class2>仅出现在第二个列表中的元素
  4. 有快速的方法吗?

1 个答案:

答案 0 :(得分:10)

var requirement1 = list1.Intersect(list2);
var requirement2 = list1.Except(list2);
var requirement3 = list2.Except(list1);

对于List<string>,这就是您所需要的一切。如果您是为自定义类执行此操作而您正在寻找除引用比较之外的其他内容,则需要确保该类正确覆盖EqualsGetHashCode。或者,您可以为上述方法的重载提供IEqualityComparer<YourType>

修改:

好的,现在你在评论中指出它不是字符串列表,它是List<MyObject>。在这种情况下,重写Equals / GetHashCode(如果您的密钥应始终唯一地标识这些类并且您可以访问源代码)或提供IEqualityComparer实现(仍然涉及Equals / GetHashCode,如果比较对于这些是唯一的,请使用此需要或者如果您无权访问MyObject源代码。

例如:

class MyObjectComparer : IEqualityComparer<MyObject>
{
     public bool Equals(MyObject x, MyObject y)
     {
          // implement appropriate comparison of x and y, check for nulls, etc 
     }

     public int GetHashCode(MyObject obj)
     {
          // validate if necessary
          return obj.KeyProperty.GetHashCode();
     }
}

如果您使用了这样的自定义相等比较器,则对上述方法的调用将是

list1.Intersect(list2, customComparerInstance);

编辑:现在你再次移动了这个栏,这次问题涉及两个不同的类。为此,您可以考虑使用连接操作,一个是内部操作,另一个是外部操作。

的情况下
class Class1
{
    public string Foo { get; set; } 
}

class Class2
{
    public string Bar { get; set; }
}

你可以写

var intersect = from item1 in list1
                join item2 in list2
                on item1.Foo equals item2.Bar
                select item1;

var except1 = from item1 in list1
                join item2 in list2
                on item1.Foo equals item2.Bar into gj
                from item2 in gj.DefaultIfEmpty()
                where item2 == null
                select item1;

要获取list2中的项目而不匹配list1中的*对象,只需颠倒except1查询中列表/项目的顺序。