如何利用自定义AreCoordinatesEqual方法验证changedGeometry列表的所有坐标均存在于defaultGeometry列表中
嘿,先提个小细节:你当前的嵌套循环代码里有个逻辑错误——内层循环里你写的是changedGeometry[i],但应该是changedGeometry[j]哦,这个错误会导致你没法正确遍历changedGeometry里的所有元素,得先把这个修正过来。
接下来针对你的需求(验证changedGeometry的每一个坐标都能在defaultGeometry中找到匹配项,用自定义的AreCoordinatesEqual方法判断),我给你几种更优的实现思路:
1. 修正后的基础嵌套循环
先把最基础的逻辑改对,确保功能正常:
for (int j = 0; j < changedGeometry.Count; j++) { bool foundMatch = false; for (int i = 0; i < defaultGeometry.Count; i++) { if (AreCoordinatesEqual(defaultGeometry[i], changedGeometry[j])) { foundMatch = true; break; // 找到匹配就跳出内层循环,不用继续遍历了 } } if (!foundMatch) { return false; // 有一个元素没找到匹配就直接返回false } } return true; // 所有元素都找到匹配,验证通过
这个版本修正了索引错误,而且加入了提前跳出内层循环的逻辑,比你原来的写法效率更高一点。
2. 使用LINQ简化代码
如果你用的是C# 3.0及以上版本,LINQ能让代码变得非常简洁易读,逻辑和上面的循环完全一致:
return changedGeometry.All(changedCoord => defaultGeometry.Any(defaultCoord => AreCoordinatesEqual(defaultCoord, changedCoord)));
All方法会检查changedGeometry里的每一个元素是否都满足后续条件,Any则负责验证defaultGeometry中是否存在匹配的坐标。这种写法省去了手动管理循环索引的麻烦,可读性拉满。
3. 预处理优化(适合多次验证场景)
如果需要频繁执行这个验证逻辑,或者defaultGeometry的元素规模很大,建议提前把defaultGeometry转换成支持快速查找的结构,比如自定义哈希集合。因为默认的HashSet<T>依赖object.Equals和object.GetHashCode,所以我们需要自定义一个IEqualityComparer来适配AreCoordinatesEqual:
首先定义坐标比较器:
public class CoordinateEqualityComparer : IEqualityComparer<Coordinate> // 这里假设你的坐标类型是Coordinate { public bool Equals(Coordinate x, Coordinate y) { return AreCoordinatesEqual(x, y); } public int GetHashCode(Coordinate obj) { // 这里需要根据你的坐标结构实现合适的哈希逻辑,确保相等的坐标返回相同哈希值 // 比如二维坐标可以这么写: return obj.X.GetHashCode() ^ obj.Y.GetHashCode(); } }
然后预处理defaultGeometry为哈希集合:
var defaultCoordsSet = new HashSet<Coordinate>(defaultGeometry, new CoordinateEqualityComparer());
之后每次验证只需要一行代码,查找效率从O(n)直接提升到O(1):
return changedGeometry.All(coord => defaultCoordsSet.Contains(coord));
这种方案的优势是预处理一次,多次使用时性能提升非常明显,尤其当两个集合的元素数量都很大的时候。
最后说下各方案的适用场景:
- 如果你只是偶尔执行一次验证,或者集合规模很小,用LINQ或者修正后的嵌套循环就足够了,代码简洁易维护。
- 如果需要频繁执行验证,或者集合元素数量较多,一定要用预处理哈希集合的方案,能大幅降低时间开销。
内容的提问来源于stack exchange,提问作者Özgür Yıldırım

