我有List<CustomObject>
并希望从中删除重复项。
如果两个自定义对象具有相同的property: City
值,那么我将其称为重复
我已经实现了如下IEquatable,但是无法从列表中删除重复项。
缺少什么?
public class CustomAddress : IAddress, IEqualityComparer<IAddress>
{
//Other class members go here
//IEqualityComparer members
public bool Equals(IAddress x, IAddress y)
{
// Check whether the compared objects reference the same data.
if (ReferenceEquals(x, y)) return true;
// Check whether any of the compared objects is null.
if (ReferenceEquals(x, null) || ReferenceEquals(y, null))
return false;
// Check whether the Objects' properties are equal.
return x.City.Equals(y.City);
}
public int GetHashCode(IAddress obj)
{
// Check whether the object is null.
if (ReferenceEquals(obj, null)) return 0;
int hashAreaName = City == null ? 0 : City.GetHashCode();
return hashAreaName;
}
}
我正在使用.NET 3.5
答案 0 :(得分:1)
如果你有Equals
和GetHashCode
的覆盖,如果你有一个需要过滤的现有列表,只需调用Distinct()
(可通过命名空间System.Linq获得)清单。
var noDupes = list.Distinct();
这将为您提供无重复的序列。如果您需要将其作为具体列表,只需在调用结束时添加ToList()
即可。
var noDupes = list.Distinct().ToList();
另一个答案提到实施IEqualityComparer<CustomObject>
。当直接覆盖Equals
和GetHashCode
是不可能的(你不控制源代码)或没有意义时(在这种特殊情况下你的平等概念对于类来说不是通用的),这很有用。在这种情况下,定义比较器as demonstrated并将比较器的实例提供给Distinct
的重载。
最后,如果您要从头开始构建列表并希望避免插入重复项,则可以使用HashSet<T>
,如上所述here。 HashSet还在构造函数中接受自定义比较器,因此您可以选择包含它。
var mySet = new HashSet<CustomObject>();
bool isAdded = mySet.Add(myElement);
// isAdded will be false if myElement already exists in set, and
// myElement would not be added a second time.
// or you could use
if (!mySet.Contains(myElement))
mySet.Add(myElement);
另一个不使用.NET库方法但在紧要关头可用的选项是Jon Skeet的DistinctBy
,您可以看到粗略的实现here。我们的想法是您直接提交Func<MyObject, Key>
lambda表达式,并完全忽略Equals
和GetHashCode
(或自定义比较器)的覆盖。
var noDupes = list.DistinctBy(obj => obj.City); // NOT part of BCL
答案 1 :(得分:0)
要仅在特定属性上匹配重复项,您需要比较器。
class MyComparer : IEqualityComparer<CustomObject>
{
public bool Equals(CustomObject x, CustomObject y)
{
return x.City.Equals(y.City);
}
public int GetHashCode(CustomObject x)
{
return x.City.GetHashCode()
}
}
用法:
var yourDistictObjects = youObjects.Distinct(new MyComparer());
编辑:找到了能够满足您需求的线程,我想我过去曾提到过它:
Remove duplicates in the list using linq
我认为一个有趣的答案(但不是如何做到的)是:
var distinctItems = items.GroupBy(x => x.Id).Select(y => y.First());
这是一个可以满足您需要的单线,但可能没有其他方法那么高效。
答案 2 :(得分:0)
只需按照您的方式实施.Equals
(如果您正确实施),就不会阻止将重复项添加到List<T>
。您实际上必须手动删除它们。
而不是List<CustomObject>
使用HashSet<CustomObject>
。它永远不会包含重复项。
答案 3 :(得分:0)
那是因为List<CustomObject>
会测试您的班级(CustomObject
)是否实施IEquatable<CustomObject>
而不是IEquatable<IAddress>
我认为在添加新成员之前,对于重复检查,您使用的是Contains方法