另一个 Swift 3 替代方案是使用全局 sequence(state:next:) method。
斯威夫特 3.1
let number = 123456
let array = Array(sequence(state: number,
next: { return $0 > 0 ? ($0 % 10, $0 = $0/10).0 : nil }
).reversed())
print(array) // [1, 2, 3, 4, 5, 6]
Swift 3.0
let number = 123456
let array = Array(sequence(state: number,
next: { (num: inout Int) -> Int? in
return num > 0 ? (num % 10, num /= 10).0 : nil
}).reversed())
print(array) // [1, 2, 3, 4, 5, 6]
上面的方法假设一个非负数,而且如果number 是0,将返回一个空数组([])。涵盖自然数的全部范围如下:
// -123 -> [1, 2, 3]
// 0 -> [0]
// 123 -> [1, 2, 3]
我们可以将上面的修改为:
// for some number ...
let number = ...
// Swift 3.1
let array: [Int]
if number == 0 { array = [0] }
else {
array = Array(sequence(state: abs(number),
next: { return $0 > 0 ? ($0 % 10, $0 = $0/10).0 : nil }
).reversed())
}
// Swift 3.0
let array: [Int]
if number == 0 { array = [0] }
else {
array = Array(sequence(state: number,
next: { (num: inout Int) -> Int? in
return num > 0 ? (num % 10, num /= 10).0 : nil
}).reversed())
}
有关上述元组返回的一些细节
在上面的单行 return 中,我们使用了整洁的 "()-return 操作作为 ()" 类型的元组成员内联,这是我第一次看到使用的方法@MartinR 在他的改进建议中更新the following answer。我们使用(Int, ()) 元组的最后一个成员来改变state 属性num;元组的第一个成员将在“计算”第二个元组成员中执行()-return 操作之前计算。
我们可以在这个元组方法和使用单个defer 和return 语句执行闭包的方法之间进行类比。即return 声明:
return num > 0 ? (num % 10, num /= 10).0 : nil
也可以通过执行这样的闭包来完成(在此上下文中为“长格式”)
return num > 0 ? { defer { num /= 10 }; return num % 10 }() : nil
我没有对这两种方法进行相互基准测试,但我感觉前者在重复调用时会更快,如上述sequence(state:next:) 的上下文中。
Swift 3.0 与 3.1:上述 next 闭包中的匿名参数
由于 SR-1976 中报告的现已关闭的(Swift 3.1 及更高版本)错误(Swift 3 中的闭包签名需要 inout 参数),因此 Swift 对 inout 的类型推断存在限制闭包的参数。参见例如详情如下问答:
这就是为什么我们必须在上面的 Swift 3.0 解决方案的 next 闭包中显式注释 state 的类型,而我们可以在 Swift 的 next 闭包中使用匿名参数3.1解决方案。