C#中使用Except处理锯齿数组异常,如何获取目标数组独有元素
解决锯齿数组使用Enumerable.Except提取唯一元素的问题
问题出在Enumerable.Except的默认行为上:对于int[]这种引用类型,它默认比较的是数组的引用地址,而不是数组里的元素内容。哪怕两个数组的元素完全一样,只要是不同的数组实例,就会被判定为不相等,所以你调用后会返回整个proposedLocation数组。
下面给你两种可行的解决方案,都能保留int[][]类型的结果:
方案一:自定义数组相等比较器
先写一个实现IEqualityComparer<int[]>的比较器类,让Except能根据数组内容判断是否相等:
public class IntArrayEqualityComparer : IEqualityComparer<int[]> { public bool Equals(int[] x, int[] y) { if (ReferenceEquals(x, y)) return true; if (x is null || y is null) return false; // 先比长度,再逐个比对元素 return x.Length == y.Length && x.SequenceEqual(y); } public int GetHashCode(int[] obj) { if (obj is null) return 0; // 结合所有元素的哈希值生成数组的哈希码 int hash = 17; foreach (int num in obj) { hash = hash * 31 + num.GetHashCode(); } return hash; } }
然后调用Except时传入这个比较器:
// 替换成你自己的数组实例 int[][] currentLocation = new int[][] { new int[] {10,12}, new int[] {11,13} }; int[][] proposedLocation = new int[][] { new int[] {10,12}, new int[] {11,13}, new int[] {11,14}, new int[] {11,15} }; // 提取仅在proposedLocation中存在的元素,结果为int[][] var uniqueElements = proposedLocation.Except(currentLocation, new IntArrayEqualityComparer()).ToArray();
方案二:用LINQ直接过滤(无需额外类)
如果不想写自定义比较器,直接用Where结合SequenceEqual过滤也能实现:
var uniqueElements = proposedLocation .Where(proposedArr => !currentLocation.Any(currentArr => currentArr.SequenceEqual(proposedArr))) .ToArray();
这段代码会逐个检查proposedLocation里的数组,只保留那些在currentLocation中找不到内容完全匹配的数组,最后转成int[][]类型。
两种方案的区别:方案一在数组数量较多时性能更好,因为Except内部会用哈希表做优化;方案二写法更简洁,适合数据量不大的场景。
内容的提问来源于stack exchange,提问作者nemethv
相关产品推荐
相关产品推荐

