无法在List <class> </class>中删除重复项

时间:2014-06-27 18:55:01

标签: c# visual-studio-2010 list duplicates ienumerable

我有一个班级和名单:

    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();

但两者都以与以前相同的条件返回列表,并带有重复项。

4 个答案:

答案 0 :(得分:1)

您需要覆盖/实施Equals()GetHashCode(),现在您正在列出不同的实例,并且它们彼此正确地完全相同/唯一。

答案 1 :(得分:1)

您遇到的问题是对象的身份不是您的想法。你的直觉告诉你,身份是firstParamsecondParam的组合。真正发生的是className的每个不同实例都有自己的身份,不依赖于对象的实现。您需要覆盖通过System.Object提供的方法,主要是EqualsGetHashCode,尽管您可能不会覆盖GetHashCode(哈希集需要这样才能使用)正常。)

答案 2 :(得分:1)

如果您的班级只包含这两个字段,那么您可以执行EqualsGetHashCode而不是实施:

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());

上面的代码会在属性firstParamsecondParam上进行分组,稍后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());

这允许您在单次拍摄时区分对象,而无需实现EqualsGetHashCode。例如,如果项目中有一个位置,您调用此类Distinct,则可能足以使用此扩展名。另一方面,如果className对象的身份是跨越许多方法和类的概念,那么确定最好只定义EqualsGetHashCode

相关问题