【C#】list 去重

原文: 【C#】list 去重

 

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

有兩個重載方法:數組

複製代碼
//
        // 摘要: 
        //     經過使用默認的相等比較器對值進行比較返回序列中的非重複元素。
        //
        // 參數: 
        //   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>的實現對象ide

1.值類型元素集合去重post

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 5this

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

首先自定義一個Student類spa

複製代碼
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方法去重.net

複製代碼
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()));
複製代碼

執行結果:code

可見,並無去除重複的記錄。orm

不帶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

相關文章
相關標籤/搜索