如何在保留元素原始顺序的同时移除C# List<T>中的重复值?
C# List去重并保留元素首次出现顺序的高效实现
要实现移除List<int>中的重复值、保留首次出现顺序的需求,有几种高效简洁的方案,分场景说明如下:
1. .NET 6及更高版本:直接用LINQ的Distinct()
从.NET 6开始,Enumerable.Distinct()方法的实现已改为保留元素首次出现的顺序,代码极简且高效:
List<int> numbers = new List<int> { 1, 2, 3, 2, 4, 3, 5 }; var distinctNumbers = numbers.Distinct().ToList(); // 结果:{ 1, 2, 3, 4, 5 }
该方法内部基于哈希表实现,时间复杂度为O(n),和手动实现的效率一致。
2. 兼容旧版本(.NET Framework/.NET Core <3.x):自定义扩展方法
如果项目基于旧版.NET框架,Distinct()不保证顺序,可封装一个基于HashSet的扩展方法,仅遍历一次列表,时间复杂度O(n),是最优的手动实现方式:
public static class ListExtensions { public static List<T> DistinctPreserveOrder<T>(this List<T> source) { var seen = new HashSet<T>(); var result = new List<T>(source.Count); // 预分配容量,提升性能 foreach (var item in source) { // HashSet.Add()返回true表示元素未存在,此时加入结果列表 if (seen.Add(item)) { result.Add(item); } } return result; } }
使用方式:
var distinctNumbers = numbers.DistinctPreserveOrder();
为什么单纯用HashSet不行?
HashSet<T>本身是无序集合,直接将List转为HashSet再转回List会打乱元素的原始顺序,因此不能直接采用这种方式。
方案对比
- .NET 6+的
Distinct():代码最简洁,无需额外实现,推荐优先使用。 - 自定义扩展方法:兼容所有.NET版本,性能最优,适合需要兼容旧项目的场景。
内容的提问来源于stack exchange,提问作者hossein javadi
相关产品推荐
相关产品推荐

