1. 程式人生 > >【C#】list 去重

【C#】list 去重

student AR 復制 泛型 沒有 obb 去重 archive func

原文:【C#】list 去重

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

有兩個重載方法:

技術分享圖片
        //
        // 摘要: 
        //     通過使用默認的相等比較器對值進行比較返回序列中的非重復元素。
        //
        // 參數: 
        //   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);    
技術分享圖片

第一個方法不帶參數,第二個方法需要傳一個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類

技術分享圖片 技術分享圖片
    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);
        }
    }
技術分享圖片

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

技術分享圖片
            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()));   
技術分享圖片

執行結果:技術分享圖片

可見,並沒有去除重復的記錄。

不帶comparer參數的Distinct方法是使用的IEqualityComparer接口的默認比較器進行比較的,對於引用類型,默認比較器比較的是其引用地址,程序中集合裏的每一個元素都是個新的實例,引用地址都是不同的,所以不會被作為重復記錄刪除掉。

因此,我們考慮使用第二個重載方法。

新建一個類,實現IEqualityComparer接口。註意GetHashCode方法的實現,只有HashCode相同才會去比較

技術分享圖片
    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();
        }
    }
技術分享圖片

然後調用

list.Distinct(new Compare()).ToList().ForEach(s => Console.WriteLine(s.ToString()));

執行結果:技術分享圖片

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

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

技術分享圖片 技術分享圖片
    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));
        }
    }
技術分享圖片

調用:

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

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

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

【C#】list 去重