在LINQ中使用Union合并列表时删除重复项

时间:2013-06-07 09:16:42

标签: c# linq

我正在尝试使用list.Union中的LinqPad合并两个列表,但我无法让它工作,并希望检查我的理解是否正确。

鉴于这个简单的课程:

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<Test> list = new List<Test>();
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<Test> list2 = new List<Test>();
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

我做错了什么或者我误解了吗?

此外,它是否可以在没有明确覆盖Equals类中的Test方法的情况下工作?

由于

4 个答案:

答案 0 :(得分:12)

在你的情况下,你只需定义一些LINQ一无所知的方法。这就像创建方法bool HeyEquateMeWith(Test other)并期望LINQ在执行set操作时会调用它。

您需要将您的课程定义为以下内容(覆盖 Object的{​​{1}}和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(); } } 会调用您重写的UnionEquals方法。另外,当您覆盖GetHashCode方法时,您应该ALWAYS覆盖GetHashCode

答案 1 :(得分:1)

您可以创建一个实现

的类
IEqualityComparer<Test>

此类是否定义了Equals和GetHashCode 之后,您可以将此比较器传递给Union方法 就像那样:

public class MyComparer:IEqualityComparer<Test>{
//Equals and GetHashCode
}

var mergedList = list.Union(list2, new MyComparer()).ToList();

答案 2 :(得分:1)

只是想把这个留给那些仍然无法得到它的人。我发现这篇文章对从IEqualityComparer继承的compare类非常有帮助  http://alicebobandmallory.com/articles/2012/10/18/merge-collections-without-duplicates-in-c

答案 3 :(得分:0)

如果对默认比较器不满意,可以尝试类似的东西(反过来,使用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();