我有一个班级和名单:
public class className
{
public string firstParam { get; set; }
public string secondParam { get; set; }
}
public static List<className> listName = new List<className>();
该列表包括(例如):
Apple Banana
Corn Celery
Corn Celery
Corn Grapes
Raisins Pork
我正在尝试编辑列表(或创建新列表)以获取:
Apple Banana
Corn Celery
Corn Grapes
Raisins Pork
我试过了:
var listNoDupes = listName.Distinct();
和
IEnumerable<className> listNoDupes = listName.Distinct();
但两者都以与以前相同的条件返回列表,并带有重复项。
答案 0 :(得分:1)
您需要覆盖/实施Equals()
和GetHashCode()
,现在您正在列出不同的实例,并且它们彼此正确地完全相同/唯一。
答案 1 :(得分:1)
您遇到的问题是对象的身份不是您的想法。你的直觉告诉你,身份是firstParam
和secondParam
的组合。真正发生的是className
的每个不同实例都有自己的身份,不依赖于对象的实现。您需要覆盖通过System.Object
提供的方法,主要是Equals
和GetHashCode
,尽管您可能不会覆盖GetHashCode
(哈希集需要这样才能使用)正常。)
答案 2 :(得分:1)
如果您的班级只包含这两个字段,那么您可以执行Equals
和GetHashCode
而不是实施:
var listNoDupes = listName.GroupBy(r => new { r.firstParam, r.secondParam })
.Select(grp => grp.First())
.ToList();
或者你可以得到一个IEnumerable<T>
,如:
IEnumerable<className> listNoDupes =
listName
.GroupBy(r => new { r.firstParam, r.secondParam })
.Select(grp => grp.First());
上面的代码会在属性firstParam
和secondParam
上进行分组,稍后grp.First
会从群组中返回一个项目,您将从每个群组中找到一个项目, (无重复)
答案 3 :(得分:1)
还有第三种可能性 - 使用Distinct
方法版本需要IEqualityComparer
。不幸的是,C#不支持创建匿名的临时接口实现。我们可以创建帮助类和扩展名:
public static class IEnumerableExtensions
{
public class LambdaEqualityComparer<T> : IEqualityComparer<T>
{
private Func<T, T, bool> comparer;
private Func<T, int> hash;
public LambdaEqualityComparer(Func<T, T, bool> comparer,
Func<T, int> hash)
{
this.comparer = comparer;
this.hash = hash;
}
public bool Equals(T x, T y)
{
return comparer(x, y);
}
public int GetHashCode(T x)
{
return hash(x);
}
}
public static IEnumerable<T> Distinct<T>(this IEnumerable<T> elems,
Func<T, T, bool> comparer,
Func<T, int> hash)
{
return elems.Distinct(new LambdaEqualityComparer<T>(comparer, hash));
}
}
然后我们可以为Distinct
方法提供lambdas:
var filteredList = myList.Distinct((x, y) => x.firstParam == y.firstParam &&
x.secondParam == y.secondParam,
x => 17 * x.firstParam.GetHashCode() + x.secondParam.GetHashCode());
这允许您在单次拍摄时区分对象,而无需实现Equals
和GetHashCode
。例如,如果项目中有一个位置,您调用此类Distinct
,则可能足以使用此扩展名。另一方面,如果className
对象的身份是跨越许多方法和类的概念,那么确定最好只定义Equals
和GetHashCode
。