Вот мое решение. Вместо того, чтобы вручную управлять индексами, я использую два итератора. Тот, который продвигается вперед, обозначая «начало» прогонов, и тот, который мчится вперед, чтобы найти «концы» трасс.
Я усовершенствовал мой код для работы с любым Sequence
(не только Array
) и любым типом Strideable
(любым типом, который определяет distance(to:)
, не обязательно просто Int
).
extension Sequence where Element: Strideable {
func splitConsequtiveRuns() -> [[Element]] {
var runs = [[Element]]()
var runStartIterator = self.makeIterator()
while let startElement = runStartIterator.next() {
var runEndIterator = runStartIterator
var prevElement = startElement
var run = [startElement]
while let nextElement = runEndIterator.next(),
prevElement.distance(to: nextElement) == 1 {
_ = runStartIterator.next() // advance the "start" iterator, to keep pace
prevElement = nextElement // update this, for use in then next loop's comparison
run.append(nextElement)
}
runs.append(run)
}
return runs
}
}
let array: [Int] = [0...3, 8...8, 10...15].flatMap { $0 }
print(array.splitConsequtiveRuns()) // => [[0, 1, 2, 3], [8], [10, 11, 12, 13, 14, 15]]