Swift中如何调用自定义二分搜索函数?C开发者遇调用难题
Swift二分搜索函数调用问题修复
问题核心
作为资深C语言开发者,移植C的二分搜索逻辑到Swift后,编译通过但调用时编译器要求手动给eleCompare传参,无法实现由bsearch自动传入参数的预期,同时代码还存在参数不匹配、类型不安全等隐性问题。
问题分析
- 参数名不匹配:
bsearch函数定义的第一个参数是arr:[Any],但函数内部却用v访问数组,属于笔误;调用时又用v:传递参数,和定义的参数名arr不对应。 - 函数类型不兼容:
bsearch要求的比较函数类型是(Any, Double)->Int,但eleCompare的类型是(locArrayele, Double)->Int,且Swift中函数参数标签必须匹配(eleCompare带left:/right:标签,而bsearch的闭包要求无标签)。 - 类型不安全:使用
[Any]会导致数组元素访问时的类型隐患,应该用泛型实现类型安全的二分搜索。 - 语法错误:测试代码的
print语句缺少闭合双引号,且未导入CoreLocation框架(CLLocationDegrees依赖该框架)。
修复后的完整代码
1. 泛型版二分搜索函数(类型安全)
// 泛型实现,支持指定元素类型,避免Any带来的类型风险 public func bsearch<T>(v: [T], target: Double, compare: (T, Double) -> Int) -> Int { guard v.count > 1 else { return -1 } var lo = 0 var hi = v.count - 1 while hi - lo > 1 { let mid = (lo + hi) / 2 let cmpResult = compare(v[mid], target) if cmpResult == -1 { lo = mid + 1 } else { hi = mid } } if compare(v[hi], target) == 0 { return hi } return lo }
2. 调整后的比较函数(匹配闭包类型)
// 省略参数标签,匹配bsearch要求的闭包参数格式 func eleCompare(_ left: locArrayele, _ right: Double) -> Int { if right < left.degrees { return -1 } else if right == left.degrees { return 0 } else { return 1 } }
3. 修正后的测试代码
import CoreLocation // 必须导入才能使用CLLocationDegrees class locArrayele { public var degrees: CLLocationDegrees public var ix: Int init(degrees: CLLocationDegrees, i: Int) { self.degrees = degrees self.ix = i } } public var latArray: [locArrayele] = [] // 示例:添加测试数据 latArray.append(locArrayele(degrees: 30.0, i: 0)) latArray.append(locArrayele(degrees: 34.0, i: 1)) latArray.append(locArrayele(degrees: 36.0, i: 2)) latArray.append(locArrayele(degrees: 40.0, i: 3)) // 正确调用bsearch,参数自动传入比较函数 let ix = bsearch(v: latArray, target: 35.0, compare: eleCompare) print("当纬度为35时,最接近的索引是 \(ix)")
关键修复点说明
- 泛型改造:用
T替代Any,保证数组元素类型统一,消除类型转换风险。 - 参数标签统一:比较函数使用下划线
_省略参数标签,完全匹配bsearch的闭包参数要求,传递函数时无需额外调整。 - 参数名一致性:
bsearch的参数名和调用时的参数名保持一致(均为v:),解决参数不匹配问题。 - 语法补全:补全
print语句的闭合引号,导入CoreLocation框架以使用CLLocationDegrees。
内容的提问来源于stack exchange,提问作者Michael
相关产品推荐
相关产品推荐

