简体   繁体   English

获得LIST唯一性的通用方法<T>

[英]Generic Method to get Distinct of LIST<T>

I am trying to compare (values of the properties) a instance of type in a List and eliminate duplicates. 我正在尝试比较(属性的值)列表中类型的实例,并消除重复项。 According to MSDN GetHashCode() is one of the way to compare two objects. 根据MSDN, GetHashCode()是比较两个对象的方法之一。

A hash code is intended for efficient insertion and lookup in collections that are based on a hash table. 哈希码用于在基于哈希表的集合中进行有效的插入和查找。 A hash code is not a permanent value 哈希码不是永久值

Considering that, I started writing my extension method as bellow 考虑到这一点,我开始以下面的方式编写扩展方法

 public static class Linq 
    {
  public static IEnumerable<T> DistinctObjects<T>(this IEnumerable<T> source)
        {
            List<T> newList = new List<T>();
            foreach (var item in source)
            {
                if(newList.All(x => x.GetHashCode() != item.GetHashCode()))
                    newList.Add(item);
            }
            return newList;
        }
}

This condition always gives me false though the data of the object is same. 尽管对象的数据相同,但这种情况总是给我false的提示。

newList.All(x => x.GetHashCode() != item.GetHashCode())

Finally I would like to use it like 最后我想像

MyDuplicateList.DistinctObjects().ToList();

If comparing all fields of the object is too much, I am okay to use it like, 如果比较对象的所有字段太多,我可以这样使用它,

 MyDuplicateList.DistinctObjects(x=>x.Id, x.Name).ToList();

Here I am telling compare only these two fields of those objects. 在这里,我要告诉您只比较这些对象的这两个字段。

After reading your comments I would propose this solution: 阅读您的评论后,我将提出以下解决方案:

   public static IEnumerable<TSource> DistinctBy<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector)
    {
        HashSet<TResult> set = new HashSet<TResult>();

        foreach(var item in source)
        {
            var selectedValue = selector(item);

            if (set.Add(selectedValue))
                yield return item;
        }
    }

Then you can use it like this: 然后,您可以像这样使用它:

var distinctedList = myList.DistinctBy(x => x.A);

or for multiple properties like that: 或类似的多个属性:

var distinctedList = myList.DistinctBy(x => new {x.A,x.B});

The advantage of this solution is you can exactly specify what properties should be used in distinction and you don't have to override Equals and GetHashCode for every object. 该解决方案的优点是,您可以精确地指定应使用哪些属性来进行区分,而不必为每个对象覆盖EqualsGetHashCode You need to make sure that your properties can be compared. 您需要确保可以比较您的属性。

You shouldn't need to create your own custom, generic method for this. 您不需要为此创建自己的自定义通用方法。 Instead, provide a custom EqualityComparar for your data type: 而是为您的数据类型提供自定义EqualityComparar

var myDuplicates = myList.Distinct(new MyComparer());

Where you define a custom Comparer like this: 在此处定义自定义比较器的位置如下:

public class MyComparer : IEqualityComparer<Mine>
{
    public bool Equals(Mine x, Mine y)
    {
        if (x == null && y == null) return true;            
        if (x == null || y == null) return false;
        return x.Name == y.Name && x.Id == y.Id;
    }

    public int GetHashCode(Mine obj)
    {
        return obj.Name.GetHashCode() ^ obj.Id.GetHashCode();
    }
}

Edit: I initially had incorrect code here, this should do what you want without you having to override an Equals operator 编辑:我最初在这里有不正确的代码,这应该做您想要的而不必重写Equals运算符

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM