You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

按经度排序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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:43:17