问题
let x = (0..<10).splitEvery( 3 ) XCTAssertEqual( x, [(0...2),(3...5),(6...8),(9)], "implementation broken" )
注释
我在计算范围中的元素数量等时遇到问题…
extension Range { func splitEvery( nInEach: Int ) -> [Range] { let n = self.endIndex - self.startIndex // ERROR - cannot invoke '-' with an argument list of type (T,T) } }
范围中的值是ForwardIndexType,因此您只能使用advance()它们或计算distance(),但是-未定义减法。预付款必须是相应的类型T.Distance。因此,这可能是一种实现:
ForwardIndexType
advance()
distance()
-
T.Distance
extension Range { func splitEvery(nInEach: T.Distance) -> [Range] { var result = [Range]() // Start with empty array var from = self.startIndex while from != self.endIndex { // Advance position, but not beyond the end index: let to = advance(from, nInEach, self.endIndex) result.append(from ..< to) // Continue with next interval: from = to } return result } }
例:
println( (0 ..< 10).splitEvery(3) ) // Output: [0..<3, 3..<6, 6..<9, 9..<10]
但是请注意,这0 ..< 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 是 协议 和协议不能扩展。你可以做的反而是定义一个 函数 ,是以可切片的对象作为第一个参数:
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) ) // Output: [ab, cd, ef, g] println( splitEvery([3.1, 4.1, 5.9, 2.6, 5.3], 2) ) // Output: [[3.1, 4.1], [5.9, 2.6], [5.3]]
范围是不可切片的,但是您可以定义一个带有range参数的单独函数:
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]