C#中如何忽略顺序移除Tuple列表中的重复元素?
移除List<Tuple<int, int>>中顺序相反的重复项的高效实现方式
要处理这类元素相同但顺序相反的元组去重(比如(1,2)和(2,1)视为重复),以下是两种高效实现方案:
方案一:LINQ分组去重(简洁易读)
通过将每个元组标准化为「升序元素对」,再分组保留每组第一个元素,代码简洁直观:
var tupleList = new List<Tuple<int, int>>() { new Tuple<int, int>(1, 2), new Tuple<int, int>(2, 1), new Tuple<int, int>(3, 2) }; var uniqueTuples = tupleList .GroupBy(t => new { Min = Math.Min(t.Item1, t.Item2), Max = Math.Max(t.Item1, t.Item2) }) .Select(group => group.First()) .ToList(); // 最终结果:[(1,2), (3,2)]
原理:用Math.Min和Math.Max生成统一的键,让互为逆序的元组分到同一组,最终保留每组第一个出现的元组。时间复杂度为O(n log n),适合中小数据量场景。
方案二:HashSet+自定义比较器(性能最优)
通过自定义相等比较器,让HashSet识别互为逆序的元组为重复项,平均时间复杂度O(n),适合大数据量场景:
第一步:定义自定义比较器
public class ReverseTupleComparer : IEqualityComparer<Tuple<int, int>> { public bool Equals(Tuple<int, int> x, Tuple<int, int> y) { // 判断元组是否完全相同或互为逆序 return (x.Item1 == y.Item1 && x.Item2 == y.Item2) || (x.Item1 == y.Item2 && x.Item2 == y.Item1); } public int GetHashCode(Tuple<int, int> obj) { // 让互为逆序的元组生成相同哈希码 // 用元素和与积的组合确保哈希码一致 return (obj.Item1 + obj.Item2).GetHashCode() ^ (obj.Item1 * obj.Item2).GetHashCode(); } }
第二步:用HashSet过滤重复项
var tupleList = new List<Tuple<int, int>>() { new Tuple<int, int>(1, 2), new Tuple<int, int>(2, 1), new Tuple<int, int>(3, 2) }; var uniqueSet = new HashSet<Tuple<int, int>>(new ReverseTupleComparer()); var uniqueTuples = new List<Tuple<int, int>>(); foreach (var t in tupleList) { if (uniqueSet.Add(t)) { uniqueTuples.Add(t); } } // 最终结果:[(1,2), (3,2)]
原理:自定义比较器让HashSet将互为逆序的元组判定为相等,遍历原列表时仅保留首次出现的非重复元组,哈希表的平均查找时间为O(1),整体性能更优。
内容的提问来源于stack exchange,提问作者Weenhallo
相关产品推荐
相关产品推荐

