首页 > 编程语言 >C# Linq 的三种去重方式(Distinct)

C# Linq 的三种去重方式(Distinct)

时间:2022-08-15 10:15:00浏览次数:52  
标签:Name C# Age list Linq Distinct new public

 

前言

首先给出我们需要用到的对象,如下:

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

接下来我们添加100万条数据到集合中,如下:

            var list = new List<Person>();
            for (int i = 0; i < 1000000; i++)
            {
                list.Add(new Person() { Age = 18, Name = "迷恋自留地" });
            }
            for (int i = 0; i < 1000; i++)
            {
                list.Add(new Person() { Age = 19, Name = "迷恋自留地" });
            }

第一种分组去重

年龄和名称进行分组,然后取第一条即可达到去重,如下:

var  list1 = list.GroupBy(d => new { d.Age, d.Name })
    .Select(d => d.FirstOrDefault())
    .ToList();

第二种 HashSet去重 (扩展方法)

 

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

述扩展方法即可去重,如下:

 var  list2 = list.Distinct(d => new { d.Age, d.Name }).ToList();

第三种 IEqualityComparer去重 (扩展方法)

 

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;
    }
}

最终通过指定属性进行比较即可去重,如下:

list = 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;
}
  转自:https://www.modb.pro/db/104719

C# Linq 的三种去重方式(Distinct)

标签:Name,C#,Age,list,Linq,Distinct,new,public
From: https://www.cnblogs.com/sevene/p/16587236.html

相关文章

  • CF1712E2的双log解法
    令\(x=\operatorname{lcm}(i,j,k)(i<j<k)\)。如果\(x<i+j+k\),那么\(x=k\)或\(2k\)。如果\(x=k\),有\(i\vertk,j\vertk\)。离线后很容易树状数组计算。如果\(x=2......
  • HCIA学习笔记十七:Trunk接口
     一、配置Trunk接口\\创建VLAN[SWA]vlan3[SWA]vlan5\\配置端口类型[SWA-Ethernet0/3]portlink-typetrunk\\配置Trunk-Link端口PVID[SWA-Ethernet0/3]port......
  • .NET 7 发布的最后一个预览版Preview 7, 下个月发布RC
    微软在2022年8月9日发布了.NET7Preview7[1],这是它在11月10日RTM之前进入发布候选阶段之前的最后预览版。预览版7已在VisualStudio17.4预览版1中进行了测试,......
  • 【T+1 SETTLEMENT】T+1 TEST APPROACH
     Somebackgrounds:PreparingforT+1SettlementCycle|DTCCFinancialServices  https://www.dtcc.com/-/media/Files/PDFs/T2/T1-Test-Approach.pdf?mkt_tok......
  • Calling Circles UVA - 247
    原题链接思路把最短路换成是否可达即可代码#include<iostream>#include<cstdio>#include<cstring>#include<unordered_map>#include<vector>usingnamespace......
  • Oracle中DBLink的相关操作
    Oracle中的DBLink的相关操作摘要:​ DBLink,全称databasselink(数据库连接),就是在一个数据库中创建另一个数据库的连接或着说映射,然后就可以在数据库中通过tableName@DBLi......
  • CF1545B AquaMoon and Chess(要不再看一下?)
    题目大意:你有一个长为\(n\)的棋盘,这个棋盘上有一些棋子,你可以进行如下操作:如果第\(i+2\)个位置是空的,且第\(i+1\)个位置非空,则可以将第ii个位置的棋子......
  • C# 文件操作
    最近遇到一个需求,需要将超大文件中的帧头解析出来,并将帧头和数据部分分别存在文件中整体思路如下:1、读取待处理路径,根据命名规则筛选出需要处理的文件2、判断输出路径是......
  • Docker-Desktop在Ubuntu系统中的安装问题
    Docker-Desktop在Linux系统中的安装包为DEB包.deb安装包正常情况下无法直接通过UbuntuSoftware进行安装,需要安装相应的插件/支持。当然也可以通过命令行进行安装,如:su......
  • com.google.common.collect.Table 双键的Map
    com.google.common.collect.Table存放的数据,以2个键(rowKey+columnKey)一个值的形式,提供了以下方法:cellSet()rowKeySet()columnKeySet()values()以下是以学生课程实例......