Swift中按序号引用参数特性解析及相关代码疑问解答
关于Swift闭包语法糖与sorted方法的解析
1. 示例代码里到底发生了什么?
首先要明确:Swift的数组有两个核心的sorted方法:
- 无参的
numbers.sorted():默认基于元素的Comparable协议实现排序,对于Int来说就是升序排列,会返回[7, 12, 19, 20]。 - 带闭包参数的
sorted(by:):需要你传入一个闭包,自定义两个元素的比较规则——闭包接收两个元素($0和$1是Swift对闭包参数的简写,分别代表第一个和第二个参数),返回一个Bool值,告诉排序算法:$0是否应该排在$1的前面。
你写的numbers.sorted {$0 > $1}是sorted(by:)的语法糖简化写法:
- 因为闭包是这个方法的最后一个参数,所以可以把闭包从括号里移到外面;
- 又因为这个闭包是方法的唯一参数,所以可以直接省略掉原有的括号。
等价于完整写法:
let sortedNumbers = numbers.sorted(by: { (a: Int, b: Int) -> Bool in return a > b })
这个闭包定义的是“降序规则”,所以最终得到[20, 19, 12, 7]——你说调用无参sorted()得到相同结果,应该是测试时的小失误,两者结果是相反的。
2. 闭包$0 > $1什么时候运行?
这个闭包和Python里的lambda类似,是在排序算法执行的过程中被多次调用:
排序算法(Swift底层用的是Timsort)在比较数组中两两元素的相对位置时,每次都会调用这个闭包,传入要比较的两个元素,根据返回的Bool值决定这两个元素是否需要交换位置。整个排序完成后,这个闭包就不会再被调用了。
3. 更直观的示例理解语法糖
用默认排序和自定义排序差异明显的场景,能更好体会这个特性:
示例1:按字符串长度排序
let fruits = ["apple", "watermelon", "pear", "grape"] // 用语法糖写法:按字符串长度降序排序 let sortedByLength = fruits.sorted { $0.count > $1.count } print(sortedByLength) // ["watermelon", "apple", "grape", "pear"] // 默认的sorted()会按字典序排序,结果完全不同 let defaultSorted = fruits.sorted() print(defaultSorted) // ["apple", "grape", "pear", "watermelon"]
示例2:自定义类型按属性排序
struct Book { let title: String let pageCount: Int } let library = [ Book(title: "Swift Programming", pageCount: 500), Book(title: "Python Crash Course", pageCount: 300), Book(title: "Effective Java", pageCount: 400) ] // 用语法糖:按页数升序排序 let sortedByPages = library.sorted { $0.pageCount < $1.pageCount } print(sortedByPages.map { $0.title }) // 输出:["Python Crash Course", "Effective Java", "Swift Programming"]
内容的提问来源于stack exchange,提问作者Tom Han
相关产品推荐
相关产品推荐

