按经度排序CLLocationCoordinate2D数组后,调用index(of:)查原索引报错求解
解决CLLocationCoordinate2D数组查找索引的问题
你遇到的错误是因为CLLocationCoordinate2D这个CoreLocation结构体默认没有遵循Equatable协议,而数组的index(of:)方法要求元素必须实现Equatable,所以直接调用会失败。下面给你几种可行的解决方案,按推荐程度排序:
方案1:排序时直接保留原索引(最推荐)
这种方法不需要后续的查找操作,效率最高,还能避免重复坐标导致的索引歧义问题。思路是先把原数组的元素和对应的索引配对,再按经度排序这些配对项,最后提取原索引即可:
// 将原数组元素与索引配对 let indexedCoordinates = arrayOfCoordinates.enumerated().map { (index: $0.offset, coordinate: $0.element) } // 按经度排序配对后的数组 let sortedIndexedCoords = indexedCoordinates.sorted { $0.coordinate.longitude < $1.coordinate.longitude } // 提取排序后的原索引数组 let orderedArrayOfSelections = sortedIndexedCoords.map { $0.index }
这样一步到位就能得到你需要的orderedArrayOfSelections,完全不用循环查找,逻辑清晰还高效。
方案2:使用firstIndex(where:)自定义匹配条件
如果你坚持要在排序后的数组中反向查找原索引,可以用firstIndex(where:)方法,它不需要元素遵循Equatable,只需要你提供一个判断匹配的闭包:
let sortedArrayOfCoords = arrayOfCoordinates.sorted(by: { $0.longitude < $1.longitude }) var orderedArrayOfSelections = [Int]() for coord in sortedArrayOfCoords { // 自定义匹配逻辑:比较纬度和经度 if let index = arrayOfCoordinates.firstIndex(where: { // 注意:浮点数直接比较可能有精度问题,建议加误差容忍 abs($0.latitude - coord.latitude) < 1e-6 && abs($0.longitude - coord.longitude) < 1e-6 }) { orderedArrayOfSelections.append(index) } else { // 处理找不到匹配项的情况,比如添加默认值-1 orderedArrayOfSelections.append(-1) } }
⚠️ 注意:如果原数组中有完全相同的坐标,firstIndex(where:)只会返回第一个匹配的索引,这可能和你预期的结果不一致,所以这种方法不如方案1可靠。另外,浮点数直接用==比较容易出现精度误差,建议用一个极小的容忍值(比如1e-6)来判断是否相等。
方案3:让CLLocationCoordinate2D遵循Equatable协议
你可以扩展CLLocationCoordinate2D,让它实现Equatable协议,这样就能直接使用firstIndex(of:)方法了:
import CoreLocation extension CLLocationCoordinate2D: Equatable { public static func == (lhs: CLLocationCoordinate2D, rhs: CLLocationCoordinate2D) -> Bool { // 同样建议加入精度容忍,避免浮点数误差 let tolerance = 1e-6 return abs(lhs.latitude - rhs.latitude) < tolerance && abs(lhs.longitude - rhs.longitude) < tolerance } }
之后你就可以像最初尝试的那样调用了,不过还是要注意重复坐标的问题:
let sortedArrayOfCoords = arrayOfCoordinates.sorted(by: { $0.longitude < $1.longitude }) var orderedArrayOfSelections = [Int]() for coord in sortedArrayOfCoords { if let index = arrayOfCoordinates.firstIndex(of: coord) { orderedArrayOfSelections.append(index) } }
内容的提问来源于stack exchange,提问作者mathleticolewis
相关产品推荐
相关产品推荐

