如何在Swift中使用Filter移除坐标数组中的重复位置坐标?
在Swift中使用Filter移除CLLocationCoordinate2D数组的重复项
当然可以用filter方法来实现!问题的核心在于CLLocationCoordinate2D没有遵循Equatable或Hashable协议,所以没法直接用常规的去重逻辑。不过我们可以通过将坐标转换为可哈希的类型,配合filter和一个辅助集合来完成去重。
方法1:精确匹配坐标
如果需要严格匹配经纬度的每一位小数,可以把CLLocationCoordinate2D转换成包含经纬度的元组(Double类型是Hashable的,所以元组可以存入Set),然后在filter中维护一个已访问坐标的集合:
var seenCoordinates = Set<(latitude: Double, longitude: Double)>() let uniqueCoordinates = coodinatesArray.filter { coordinate in // 将坐标转换为可哈希的元组 let coordinateKey = (latitude: coordinate.latitude, longitude: coordinate.longitude) // 检查是否已经见过这个坐标 guard !seenCoordinates.contains(coordinateKey) else { return false // 已存在,过滤掉 } // 标记为已访问 seenCoordinates.insert(coordinateKey) return true // 保留当前坐标 }
方法2:忽略微小精度差异(更实用)
在实际场景中,GPS坐标经常会有微小的精度误差(比如你数组里的那对接近的坐标),如果需要把这类近似坐标视为重复项,可以先对经纬度进行四舍五入,再进行去重:
// 辅助函数:将坐标四舍五入到指定小数位 func roundedCoordinate(_ coordinate: CLLocationCoordinate2D, toDecimalPlaces places: Int) -> (latitude: Double, longitude: Double) { let multiplier = pow(10, Double(places)) let roundedLat = round(coordinate.latitude * multiplier) / multiplier let roundedLon = round(coordinate.longitude * multiplier) / multiplier return (roundedLat, roundedLon) } var seenCoordinates = Set<(latitude: Double, longitude: Double)>() let uniqueCoordinates = coodinatesArray.filter { coordinate in // 先四舍五入再生成匹配键 let coordinateKey = roundedCoordinate(coordinate, toDecimalPlaces: 6) guard !seenCoordinates.contains(coordinateKey) else { return false } seenCoordinates.insert(coordinateKey) return true }
原理说明
filter会遍历数组的每个元素,我们通过闭包决定是否保留当前元素- 用
Set来记录已经处理过的坐标,因为Set的查找和插入操作都是O(1)的,效率很高 - 由于
CLLocationCoordinate2D本身不可哈希,我们用元组作为“代理键”来完成重复判断
内容的提问来源于stack exchange,提问作者Abin Baby
相关产品推荐
相关产品推荐

