在LINQ中使用Union合并列表时删除重复项
我试图在LinqPad
中使用list.Union
合并两个列表,但我无法让它工作,并想检查我的理解是否正确。
鉴于这个简单的类:
public class Test { public int Id { get; set;} public int field1 { get; set; } public bool Equals(Test other) { return this.Id.Equals(other.Id); } }
两个列表填充如下:
List list = new List(); list.Add( new Test { Id = 1, field1 = 1}); list.Add( new Test { Id = 1, field1 = 2}); list.Add( new Test { Id = 2, field1 = 3}); list.Add( new Test { Id = 2, field1 = 4}); List list2 = new List(); list2.Add( new Test { Id = 1, field1 = 1}); list2.Add( new Test { Id = 1, field1 = 2}); list2.Add( new Test { Id = 2, field1 = 3}); list2.Add( new Test { Id = 2, field1 = 4});
然后我尝试: var mergedList = list.Union(list2).ToList();
并使用简单的foreach
循环输出数据并获得此输出:
ID: 1 -------- 1 ID: 1 -------- 2 ID: 2 -------- 3 ID: 2 -------- 4 ID: 1 -------- 1 ID: 1 -------- 2 ID: 2 -------- 3 ID: 2 -------- 4
我认为Union
应该删除重复的回复:
ID: 1 -------- 1 ID: 1 -------- 2 ID: 2 -------- 3 ID: 2 -------- 4
我做错了什么或者我误解了吗?
此外,它是否可以在没有显式覆盖Test
类中的Equals
方法的情况下工作?
谢谢
在您的情况下,您只需定义一些LINQ一无所知的方法。 这就像创建方法bool HeyEquateMeWith(Test other)
并期望LINQ在执行set操作时调用它。
您需要将您的类定义如下( 覆盖 Object
的Equals
和GetHashCode
方法):
public class Test { public int Id { get; set;} public int field1 { get; set; } public override bool Equals(object other) //note parameter is of type object { Test t = other as Test; return (t != null) ? Id.Equals(t.Id) : false; } public override int GetHashCode() { return Id.GetHashCode(); } }
现在Union
将调用您重写的Equals
和GetHashCode
方法。 当你重写Equals
方法时,你应该总是覆盖GetHashCode
。
您可以创建一个实现类
IEqualityComparer
这个类是否定义了Equals和GetHashCode之后你可以将这个比较器传递给你的Union方法就像这样:
public class MyComparer:IEqualityComparer{ //Equals and GetHashCode } var mergedList = list.Union(list2, new MyComparer()).ToList();
你可以尝试类似的东西,如果不满意默认比较器(反过来,利用GetHashCode方法,如@IlyaIvanov提到的):
// get all items that "other than in first list", so Where() and Any() are our filtering expressions var delta = list2.Where(x2 => !list.Any(x1 => (x1.Id == x2.Id) && (x1.field1 == x2.field1))); // now let merge two enumerables that have nothing "equal" between them var merged = list.Union(delta).ToList();
只想把它留在这里给那些仍然无法得到它的人。 我发现这篇文章对inheritance自IEqualityComparer的比较类非常有帮助http://alicebobandmallory.com/articles/2012/10/18/merge-collections-without-duplicates-in-c