当前位置: 首页 > news >正文

.NET 中如何快速实现 List 集合去重?

前言

在数据处理中,去除集合中的重复元素是一个常见的需求。.NET 6 和 .NET 7 引入了 DistinctBy 方法,这是一个非常实用的新特性,可以方便地根据指定的键对集合进行去重。

本文将详细介绍 DistinctBy 方法的使用,并通过具体的案例来展示其在实际开发中的应用。

正文

1、DistinctBy 方法

DistinctBy 方法允许我们在 LINQ 查询中根据某个键对集合中的元素进行去重。

这个方法返回一个新的集合,其中只包含根据指定键唯一确定的元素。

方法签名

public static IEnumerable<TSource> DistinctBy<TSource, TKey>(this IEnumerable<TSource> source,Func<TSource, TKey> keySelector
);

2、基本用法

最简单的用法是在 LINQ 查询中直接调用 DistinctBy 方法,然后处理去重后的集合。

说明

假设我们有一个用户列表,我们想要根据用户名去除重复的用户。

using System.Linq;
​
class User
{public string Name { get; set; }public int Age { get; set; }
}
​
var users = new List<User>
{new User { Name = "Alice", Age = 25 },new User { Name = "Bob", Age = 32 },new User { Name = "Alice", Age = 28 },new User { Name = "David", Age = 35 }
};
​
var distinctUsers = users.DistinctBy(user => user.Name);
​
foreach (var user in distinctUsers)
{Console.WriteLine($"Name: {user.Name}, Age: {user.Age}");
}

输出结果:

Name: Alice, Age: 25
Name: Bob, Age: 32
Name: David, Age: 35

过滤前后元素还是保持原有的顺序,我们可以查看源码。

源码

private static IEnumerable<TSource> DistinctByIterator<TSource, TKey>(IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey>? comparer)
{using IEnumerator<TSource> enumerator = source.GetEnumerator();
​if (enumerator.MoveNext()){var set = new HashSet<TKey>(DefaultInternalSetCapacity, comparer);do{TSource element = enumerator.Current;if (set.Add(keySelector(element))){yield return element;}}while (enumerator.MoveNext());}
}

通过查看源码,可以看到是利用了 HashSet 去重,元素顺序并未被打乱。

在处理集合时,我们经常需要去除重复的元素,同时保持原有的顺序。

使用 HashSet 可以高效地实现这一目标。

首先将指定的键尝试添加到 HashSet 中,如果添加成功,说明该键没有重复;

如果添加失败,说明已经存在相同的键,此元素将被过滤掉。

3、复杂用法

DistinctBy 方法可以用于更复杂的去重逻辑,例如根据多个属性进行去重。

说明

假设我们有一个订单列表,我们想要根据客户名称和订单金额去除重复的订单。

class Order
{public int OrderId { get; set; }public string CustomerName { get; set; }public decimal Amount { get; set; }
}
​
var orders = new List<Order>
{new Order { OrderId = 1, CustomerName = "Alice", Amount = 100.0m },new Order { OrderId = 2, CustomerName = "Bob", Amount = 150.0m },new Order { OrderId = 3, CustomerName = "Alice", Amount = 100.0m },new Order { OrderId = 4, CustomerName = "Charlie", Amount = 120.0m },new Order { OrderId = 5, CustomerName = "Bob", Amount = 150.0m }
};
​
var distinctOrders = orders.DistinctBy(order => (order.CustomerName, order.Amount));
​
foreach (var order in distinctOrders)
{Console.WriteLine($"Order ID: {order.OrderId}, Customer: {order.CustomerName}, Amount: {order.Amount}");
}

输出结果:

Order ID: 1, Customer: Alice, Amount: 100.0
Order ID: 2, Customer: Bob, Amount: 150.0
Order ID: 4, Customer: Charlie, Amount: 120.0

4、性能考虑

DistinctBy 方法在内部使用哈希表来跟踪已经出现的键,因此在大多数情况下性能非常好。但在处理非常大的数据集时,仍然需要注意内存使用情况。

说明

假设我们有一个包含数百万条记录的大集合,我们需要根据某个键进行去重。

var largeCollection = Enumerable.Range(1, 10000000).Select(i => new { Id = i, Value = i % 1000 });
var distinctLargeCollection = largeCollection.DistinctBy(item => item.Value);
Console.WriteLine($"Distinct count: {distinctLargeCollection.Count()}");

5、异步 LINQ 查询中的使用

DistinctBy 方法也可以在异步 LINQ 查询中使用,结合 IAsyncEnumerable<T> 类型,处理大量数据时更加高效。

说明

假设我们有一个异步方法返回一个用户列表,我们想要根据用户名去除重复的用户。

using System.Net.Http.Json;
​
public async IAsyncEnumerable<User> GetUsersAsync()
{var response = await httpClient.GetAsync("https://api.example.com/users");var usersJson = await response.Content.ReadAsStringAsync();// 使用Json序列化工具解析用户列表var users = JsonSerializer.Deserialize<List<User>>(usersJson);foreach (var user in users){yield return user;}
}
​
// 使用异步LINQ查询
var distinctUsers = await GetUsersAsync().DistinctByAsync(user => user.Name).ToListAsync();
​
foreach (var user in distinctUsers)
{Console.WriteLine($"Name: {user.Name}, Age: {user.Age}");
}

总结

DistinctBy 方法是 .NET 6 和 .NET 7 中 LINQ 的一个非常实用的新特性。我们在 LINQ 查询中根据指定的键对集合进行去重,简化了代码并提高了开发效率。

希望本文能帮助大家更好地理解和利用 .NET 6 和 .NET 7 中 LINQ 的 DistinctBy 方法,从而在项目中发挥更大的作用。

最后

如果你觉得这篇文章对你有帮助,不妨点个赞支持一下!你的支持是我继续分享知识的动力。如果有任何疑问或需要进一步的帮助,欢迎随时留言。也可以加入微信公众号 [DotNet技术匠] 社区,与其他热爱技术的同行一起交流心得,共同成长!

http://www.jsqmd.com/news/342059/

相关文章:

  • 扣子Coze实战:从0到1打造抖音+小红书热点监控智能体
  • 许昌英语雅思培训机构推荐;2026权威测评出国雅思辅导机构口碑榜 - 苏木2025
  • 选水浴\全温\气浴恒温振荡器,认准这些性能好的厂家! - 品牌推荐大师
  • Chebyshev Polynomials 与现代计算
  • 2026年龙门吊厂家综合对比:电动/无轨/单梁/集装箱龙门吊多场景应用分析 - 品牌推荐官
  • 毕业论文神器!实力封神的AI论文软件 —— 千笔写作工具
  • [信息论与编码理论专题-13]:如果说信息论使计算机实现人的思维提供了理论基础,那么什么理论使得计算机AI可以实现人的意识提供理论基础呢?
  • PostgreSQL、达梦、高斯、MySQL 区别
  • 2026国内最新云顶棉生产厂家top5推荐!广东广州等地优质云顶棉公司榜单发布,全品类服务双优助力服装产业升级 - 品牌推荐2026
  • C++成员访问权限以及继承权限
  • 数据驱动,安全可控:2026年企业智能BI私有化部署实力厂商推荐指南 - 品牌2025
  • 浙江餐饮业擦手纸推荐品牌 - 中媒介
  • 2026 AIGC 降重实用软件推荐(免费 + 高性价比)
  • 学习SQL心得
  • 2026户外微型水质在线监测系统(监测站)行业深度解析与优质厂家全景推荐 - 品牌推荐大师
  • 抗噪4键触摸感应玩具触摸芯片VK36N4B抗干扰4通道触摸芯片原厂提供技术支持
  • 学霸同款9个降AI率网站,千笔·降AIGC助手帮你精准降AIGC
  • 贴身定制,敏捷响应:2026年更懂本地化需求的BI部署方案商推荐名单 - 品牌2025
  • 2026年深圳到兰州整车运输公司推荐:到济南整车运输/到成都整车运输/到长沙整车运输/到福州整车运输/到西宁整车运输精选 - 品牌推荐官
  • gRPC C++ 快速编译与上手
  • STM32启动文件
  • 老字号制药企业有哪些?十大国民老厂盘点,藏着国人的健康底气 - 博客万
  • 2026年工业货架选购指南:性价比与品质如何兼得 - 2026年企业推荐榜
  • ‌商用擦手纸品牌排行 - 中媒介
  • 专精于一处,极致于体验:2026年深度集成的Deepseek知识库部署服务商精选推荐 - 品牌2025
  • 解锁智能问答与知识挖掘:2026年度值得关注的AI知识库方案商推荐 - 品牌2025
  • USACO历年白银组真题解析 | 2026年1月
  • ‌Naya是做什么的 - 中媒介
  • 生物柴油测硫仪,究竟哪个厂家的口碑好? - 品牌推荐大师
  • 深度测评 9 个降AI率工具 千笔轻松降AIGC