Swift实现支持传入函数为参数的Array扩展mapThenUnique及报错解决
报错原因解析
初始版本3个报错原因
- 报错1:
filter方法的返回值是原数组类型[Element],你直接把它转换成Array<T>赋值给mapped变量,类型不匹配。 - 报错2:你给
f传入的参数是整个数组self,但f要求的入参是单个Element类型,类型不匹配。 - 报错3:
filter要求传入的参数是一个(Element) throws -> Bool类型的闭包,你传入的是f(self)执行后返回的T类型值,完全不符合参数要求。
(Element) throws -> Bool 含义说明
这是Swift中的函数类型定义:
- 左侧的
Element代表函数接收一个Element类型的入参 - 中间的
throws代表函数执行过程中允许抛出错误 - 右侧的
Bool代表函数返回值为布尔类型
你给需要传入函数的参数位传了普通值,自然会触发类型不匹配报错。
修改后版本的问题解析
1. for循环变量名错误
你定义的映射后数组变量是 mapped,但for循环写的是 for element in filtered,filtered 变量不存在,会触发未定义标识符报错。
2. contains方法使用错误
contains(where:) 的参数要求是 (T) throws -> Bool 类型的判断闭包,你直接传入 T 类型的 element 变量,类型不匹配。
如果你要判断数组中是否已经存在当前元素,有两种正确写法:
- 直接使用不需要闭包的
contains方法:noDups.contains(element)(因为你声明了T遵守Comparable协议,而Comparable默认继承Equatable,满足contains普通版本的约束) - 坚持用
contains(where:)的话要写闭包:noDups.contains(where: { $0 == element })
3. 排序后结果的问题
你调用了noDups.sort()会对去重后的结果按升序排列,所以字符串示例返回["abc", "hi"]是正常排序结果,和你给出的功能示例要求一致。
可正常运行的最终代码
extension Array { func mapThenUnique<T: Comparable>(f: (Element) -> T) -> Array<T> { let mapped = self.map{ f($0) } var noDups: Array<T> = [] for element in mapped { if !noDups.contains(element) { noDups.append(element) } } noDups.sort() return noDups } } // 测试用例验证 print(["abc", "Hi", "AbC"].mapThenUnique { $0.lowercased() }) // 输出 ["abc", "hi"] print([2, 9, -9, 3].mapThenUnique { Int($0) * $0 }) // 输出 [4, 9, 81]
内容的提问来源于stack exchange,提问作者ThreeRingBinder
相关产品推荐
相关产品推荐

