合并无重复嵌套线路列表:LatLng数组去重实现问题咨询
解决嵌套线路列表合并去重的问题
我来帮你搞定这个线路网络合并并排除完全重复线路的需求~
首先得搞清楚为啥你之前用Distinct或者Contains没效果:
LatLng类默认没实现值相等的比较逻辑,即使两个实例的经纬度完全一样,默认的引用比较也会把它们当成不同对象- 数组是引用类型,
Contains默认比较的是数组的引用地址,而不是数组里的元素内容
要解决这个问题,我们需要分两步处理:先让LatLng能正确比较值相等,再让线路数组能基于元素内容判断是否重复。
步骤1:给LatLng实现值相等比较
因为经纬度是double类型,直接用Equals比较可能会有浮点精度误差,所以我们可以写一个自定义的坐标比较器,或者让LatLng实现IEquatable<LatLng>接口。这里推荐用单独的比较器,不用修改原类:
public class LatLngValueComparer : IEqualityComparer<LatLng> { // 自定义容差,根据业务需求调整,1e-9对应约0.1毫米的精度 private const double Tolerance = 1e-9; public bool Equals(LatLng x, LatLng y) { if (x == null && y == null) return true; if (x == null || y == null) return false; return Math.Abs(x.Latitude - y.Latitude) < Tolerance && Math.Abs(x.Longitude - y.Longitude) < Tolerance; } public int GetHashCode(LatLng obj) { if (obj == null) return 0; // 组合经纬度的哈希码,确保相等的实例哈希码一致 return HashCode.Combine(obj.Latitude.GetHashCode(), obj.Longitude.GetHashCode()); } }
步骤2:合并线路并去重
有了坐标的相等比较逻辑后,我们就可以判断两条线路是否完全重复了。这里提供两种实用的实现方式:
方式1:遍历新线路,判断后添加
把原线路转成List方便操作,然后逐个检查新线路是否已存在,不存在就添加:
// 假设你的lineNetwork和newLineNetwork都是IEnumerable<LatLng[]> var lineList = lineNetwork.ToList(); var latLngComparer = new LatLngValueComparer(); foreach (var newLine in newLineNetwork) { // 检查现有线路中是否有完全匹配的线路 bool isDuplicate = lineList.Any(existingLine => existingLine.SequenceEqual(newLine, latLngComparer)); if (!isDuplicate) { lineList.Add(newLine); } } // 转回IEnumerable<LatLng[]> lineNetwork = lineList;
方式2:用Distinct+线路比较器去重
写一个专门比较线路数组的比较器,然后用Concat合并后调用Distinct一次性去重:
public class LineEqualityComparer : IEqualityComparer<LatLng[]> { private readonly IEqualityComparer<LatLng> _latLngComparer; public LineEqualityComparer(IEqualityComparer<LatLng> latLngComparer) { _latLngComparer = latLngComparer ?? new LatLngValueComparer(); } public bool Equals(LatLng[] x, LatLng[] y) { if (x == null && y == null) return true; if (x == null || y == null) return false; // 用SequenceEqual比较数组元素,传入自定义的坐标比较器 return x.SequenceEqual(y, _latLngComparer); } public int GetHashCode(LatLng[] obj) { if (obj == null) return 0; int hash = 17; foreach (var coord in obj) { hash = hash * 31 + _latLngComparer.GetHashCode(coord); } return hash; } } // 合并并去重 lineNetwork = lineNetwork .Concat(newLineNetwork) .Distinct(new LineEqualityComparer(new LatLngValueComparer()));
这样处理后,你例子中的line2因为和line1的坐标完全一致,就会被正确识别为重复线路而排除,line1和line3则会被保留下来。
内容的提问来源于stack exchange,提问作者cullimorer
相关产品推荐
相关产品推荐

