天天看點

【C#】list 去重 

原文: 【C#】list 去重

Enumerable.Distinct 方法 是常用的LINQ擴充方法,屬于System.Linq的Enumerable方法,可用于去除數組、集合中的重複元素,還可以自定義去重的規則。

有兩個重載方法:

【C#】list 去重 
//
        // 摘要: 
        //     通過使用預設的相等比較器對值進行比較傳回序列中的非重複元素。
        //
        // 參數: 
        //   source:
        //     要從中移除重複元素的序列。
        //
        // 類型參數: 
        //   TSource:
        //     source 中的元素的類型。
        //
        // 傳回結果: 
        //     一個 System.Collections.Generic.IEnumerable<T>,包含源序列中的非重複元素。
        //
        // 異常: 
        //   System.ArgumentNullException:
        //     source 為 null。
        public static IEnumerable<TSource> Distinct<TSource>(this IEnumerable<TSource> source);
        //
        // 摘要: 
        //     通過使用指定的 System.Collections.Generic.IEqualityComparer<T> 對值進行比較傳回序列中的非重複元素。
        //
        // 參數: 
        //   source:
        //     要從中移除重複元素的序列。
        //
        //   comparer:
        //     用于比較值的 System.Collections.Generic.IEqualityComparer<T>。
        //
        // 類型參數: 
        //   TSource:
        //     source 中的元素的類型。
        //
        // 傳回結果: 
        //     一個 System.Collections.Generic.IEnumerable<T>,包含源序列中的非重複元素。
        //
        // 異常: 
        //   System.ArgumentNullException:
        //     source 為 null。
        public static IEnumerable<TSource> Distinct<TSource>(this IEnumerable<TSource> source, IEqualityComparer<TSource> comparer);          
【C#】list 去重 

第一個方法不帶參數,第二個方法需要傳一個System.Collections.Generic.IEqualityComparer<T>的實作對象

1.值類型元素集合去重

List<int> list = new List<int> { 1, 1, 2, 2, 3, 4, 5, 5 };
list.Distinct().ToList().ForEach(s => Console.WriteLine(s));      

執行結果是:1 2 3 4 5

2.引用類型元素集合去重

首先自定義一個Student類

【C#】list 去重 
【C#】list 去重 
public class Student
    {
        public string Name { get; private set; }
        public int Id { get; private set; }
        public string Hobby { get; private set; }
        public Student(string name, int id, string hobby)
        {
            this.Name = name;
            this.Id = id;
            this.Hobby = hobby;
        }
        /// <summary>
        /// 友善輸出,重寫ToString方法
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return string.Format("{0}\t{1}\t{2}", this.Name, this.Id, this.Hobby);
        }
    }      
【C#】list 去重 

使用不到參數的Distinct方法去重

【C#】list 去重 
List<Student> list = new List<Student>() { 
                new Student("James",1,"Basketball"),
                new Student("James",1,"Basketball"),
                new Student("Kobe",2,"Basketball"),
                new Student("Curry",3,"Football"),
                new Student("Curry",3,"Yoga")
            };
            list.Distinct().ToList().ForEach(s => Console.WriteLine(s.ToString()));         
【C#】list 去重 

執行結果:

【C#】list 去重 

可見,并沒有去除重複的記錄。

不帶comparer參數的Distinct方法是使用的IEqualityComparer接口的預設比較器進行比較的,對于引用類型,預設比較器比較的是其引用位址,程式中集合裡的每一個元素都是個新的執行個體,引用位址都是不同的,是以不會被作為重複記錄删除掉。

是以,我們考慮使用第二個重載方法。

建立一個類,實作IEqualityComparer接口。注意GetHashCode方法的實作,隻有HashCode相同才會去比較

【C#】list 去重 
public class Compare:IEqualityComparer<Student>
    {
        public bool Equals(Student x,Student y)
        {
            return x.Id == y.Id;//可以自定義去重規則,此處将Id相同的就作為重複記錄,不管學生的愛好是什麼
        }
        public int GetHashCode(Student obj)
        {
            return obj.Id.GetHashCode();
        }
    }      
【C#】list 去重 

然後調用

list.Distinct(new Compare()).ToList().ForEach(s => Console.WriteLine(s.ToString()));      
【C#】list 去重 

我們按照Id去給這個集合去重成功!

3.如何編寫一個具有擴充性的去重方法

【C#】list 去重 
【C#】list 去重 
public class Compare<T, C> : IEqualityComparer<T>
    {
        private Func<T, C> _getField;
        public Compare(Func<T, C> getfield)
        {
            this._getField = getfield;
        }
        public bool Equals(T x, T y)
        {
            return EqualityComparer<C>.Default.Equals(_getField(x), _getField(y));
        }
        public int GetHashCode(T obj)
        {
            return EqualityComparer<C>.Default.GetHashCode(this._getField(obj));
        }
    }
    public static class CommonHelper
    {
        /// <summary>
        /// 自定義Distinct擴充方法
        /// </summary>
        /// <typeparam name="T">要去重的對象類</typeparam>
        /// <typeparam name="C">自定義去重的字段類型</typeparam>
        /// <param name="source">要去重的對象</param>
        /// <param name="getfield">擷取自定義去重字段的委托</param>
        /// <returns></returns>
        public static IEnumerable<T> MyDistinct<T, C>(this IEnumerable<T> source, Func<T, C> getfield)
        {
            return source.Distinct(new Compare<T, C>(getfield));
        }
    }      
【C#】list 去重 

調用:

list.MyDistinct(s=>s.Id).ToList().ForEach(s => Console.WriteLine(s.ToString()));      

用到了泛型、委托、擴充方法等知識點。可以用于任何集合的各種去重場景

轉載來源:https://www.cnblogs.com/Robert-go-go/p/5399198.html

繼續閱讀