一个范围内的值属于ForwardIndexType
,因此您只能通过advance()
来提高它们的等级,
或计算distance()
,但减法 -
未定义。前进量必须是对应类型T.Distance
。因此,这是可能的实现:
extension Range {
func splitEvery(nInEach: T.Distance) -> [Range] {
var result = [Range]()
var from = self.startIndex
while from != self.endIndex {
let to = advance(from, nInEach, self.endIndex)
result.append(from ..< to)
from = to
}
return result
}
}
例子:
println( (0 ..< 10).splitEvery(3) )
// Output: [0..<3, 3..<6, 6..<9, 9..<10]
请注意,
0 ..< 10
不是一个整数列表(或数组)。要将一个数组分割成子数组,您可以定义类似的扩展:
extension Array {
func splitEvery(nInEach: Int) -> [[T]] {
var result = [[T]]()
for from in stride(from: 0, to: self.count, by: nInEach) {
let to = advance(from, nInEach, self.count)
result.append(Array(self[from ..< to]))
}
return result
}
}
例子:
println( [1, 1, 2, 3, 5, 8, 13].splitEvery(3) )
// Output: [[1, 1, 2], [3, 5, 8], [13]]
更通用的方法是将所有可切片的对象进行分割。但是Sliceable
是一个协议,无法扩展。相反,您可以定义一个函数,将可切片的对象作为第一个参数:
func splitEvery<S : Sliceable>(seq : S, nInEach : S.Index.Distance) -> [S.SubSlice] {
var result : [S.SubSlice] = []
var from = seq.startIndex
while from != seq.endIndex {
let to = advance(from, nInEach, seq.endIndex)
result.append(seq[from ..< to])
from = to
}
return result
}
请注意,此函数与上面定义的(扩展)方法完全无关。
示例:
println( splitEvery("abcdefg", 2) )
println( splitEvery([3.1, 4.1, 5.9, 2.6, 5.3], 2) )
范围不支持切片,但是您可以定义一个单独的函数,接受范围参数:
func splitEvery<T>(range : Range<T>, nInEach : T.Distance) -> [Range<T>] {
var result : [Range<T>] = []
var from = range.startIndex
while from != range.endIndex {
let to = advance(from, nInEach, range.endIndex)
result.append(from ..< to)
from = to
}
return result
}
例子:
println( splitEvery(0 ..< 10, 3) )
// Output: [0..<3, 3..<6, 6..<9, 9..<10]