Значения в диапазоне являются 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
не список (или массив) целых чисел. Для того, чтобы разбить массив в подмассивов можно определить аналогичное расширение:
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
is протокол и протоколы не могут быть расширены. Что вы можете сделать вместо этого, чтобы определить функции, которая принимает 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]]
Диапазоны повторно не sliceable, но вы могли бы определить отдельную функцию, которая принимает аргумент диапазона а:
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]
Глуховского - родовое реализацию! – kfmfe04
странно, это прекрасно работает на Playground, но у меня возникают проблемы с его компиляцией в проекте. Я разместил здесь новую запись: http://stackoverflow.com/q/26694296/975129 – kfmfe04
@ kfmfe04: У меня есть немного расширил ответ. Дайте мне знать, если вам нужна дополнительная информация. –