C# LINQ去重

C# 使用自带的Distinct无法通过某一个属性值去重,因为使用自定义扩展方法去重。
Net6版本出来了自带的DistinctBy属性。低版本没有。

扩展代码

    public static class Extensions
    {
        public static IEnumerable<T> Distinct<T>(this IEnumerable<T> source, Func<T, T, bool> comparer) where T : class
            => source.Distinct(new DynamicEqualityComparer<T>(comparer));

        private sealed class DynamicEqualityComparer<T> : IEqualityComparer<T>
            where T : class
        {
            private readonly Func<T, T, bool> _func;

            public DynamicEqualityComparer(Func<T, T, bool> func)
            {
                _func = func;
            }
            public bool Equals(T x, T y) => _func(x, y);
            public int GetHashCode(T obj) => 0;
        }

        public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
        {
            HashSet<TKey> seenKeys = new HashSet<TKey>();
            foreach (TSource element in source)
            {
                if (seenKeys.Add(keySelector(element)))
                {
                    yield return element;
                }
            }
        }
    }

实体类

        public class Person
        {
            public int Id { get; set; }
            public string Name { get; set; }
            public int Age { get; set; }
        }

调用

        var list = new List<Person>();

        //第一种方式
        var list1 = list.GroupBy(d => d.Id).Select(d => d.FirstOrDefault()).ToList();

        //第二种方式
        var list2 = list.DistinctBy(d => d.Id).ToList();

        //第三种方式
        var list3 = list.Distinct((a, b) => a.Age == b.Age && a.Name == b.Name).ToList();

性能比较

//数据量小基本没有性能问题,数据量大建议使用第三种。
var list = new List<Person>();
for (int i = 0; i < 1000000; i++)
{
    list.Add(new Person() { Age = 18, Name = "jeffcky" });
}

var time1 = Time(() =>
{
    list.GroupBy(d => new { d.Age, d.Name })
        .Select(d => d.FirstOrDefault())
        .ToList();
});
Console.WriteLine($"分组耗时:{time1}");

var time2 = Time(() =>
{
    list.Distinct(d => new { d.Age, d.Name }).ToList();
});
Console.WriteLine($"HashSet耗时:{time2}");

var time3 = Time(() =>
{
    list.Distinct((a, b) => a.Age == b.Age && a.Name == b.Name).ToList();
});
Console.WriteLine($"委托耗时:{time3}");


static long Time(Action action)
{
    var stopwatch = new Stopwatch();
    stopwatch.Start();
    action();
    stopwatch.Stop();
    return stopwatch.ElapsedMilliseconds;
}
posted @ 2022-10-08 17:00  雨水的命运  阅读(234)  评论(0编辑  收藏  举报