stride 是 Strideable 协议中定义的一个方法, 它可以按照指定的递进值生成一个序列。可以用在 Swift 的循环语法结构中。
前面我们一片文章中介绍了 Swift 3.0 删除了 C 风格循环后的几个替代方案, 后来发现还有一个方案忘了跟大家提到, 就是 stride 方法。
stride 方法定义在 Strideable 协议中。 Swift 中的大部分基础类型都实现了这个协议, 比如 Int, Float 等等。
先来看看 stride 方法的定义, 它有两种形式:
func stride(through end: Self, by stride: Self.Stride) -> StrideThrough<Self>
func stride(to end: Self, by stride: Self.Stride) -> StrideTo<Self>
一种是 stride through, 另一种是 stride to。 这两个的区别咱们直接上代码来看:
1.stride(through: 5, by: 1) // 1,2,3,4,5
1.stride(to: 5, by: 1) // 1,2,3,4
这两个调用都是生成一个从 1 到 5 的序列, 使用 through 的方式生成的序列会包含终点值(也就是5)。 使用 to 方法生成的序列不包含终点值。
for i in 1.stride(to: 5, by: 1) {
}
这样就会生成一个从 1 到 4 的遍历序列。 如果我们要遍历的是一个数组,就可以这样:
for i in 0.stride(to: arr.count, by: 1) {
}
这个循环语句从索引 0 开始遍历 arr 这个数组。 那么同样的逻辑还可以用我们之前提到的 range 方法来实现:
for i in 0..<arr.count {
}
从代码上看, 好像这种 range 的方法更加简洁, 那为什么还要用 stride 呢。 那么我们再来看看这种情况:
for i in 0.stride(to: arr.count, by: 3) {
}
这次我们其他地方都没变,只把 by 参数从 1 改到了 3。 这样 stride 生成的索引序列就变成了 0 3 6 9…
stride 相比 range 语法的方式会更加灵活, 我们可以指定索引递增的步长。 总体来说如果一般的顺序遍历,使用 range 语法会更加简单。 如果你的循环逻辑有特殊要求, 那么 stride 可以更好的满足。
注意 stride 方法返回的类型, 分别是 StrideThrough 和 StrideTo, 他们都继承自 SequenceType。 也就是说我们作用于集合类型的方法也可以应用于 stride 生成的序列:
for i in 0.stride(to: arr.count, by: 1).reverse() {
}
对序列使用 reverse 方法,就可以实现反向遍历。
并且 Swift 中除了 Int 类型, 还有很多类型实现了 Strideable 协议。 比如 Double 类型:
let pi = Double(M_PI)
0.0.stride(to: 8 * pi, by: pi)
stride 方法可以做为我们另外一个循环结构的替代方案。 结合前面说的 range 语法以及 enumeate 方法, 熟悉了时候, 你会不会也发现 C 风格的循环语法有些过时了呢。