Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Collection.split(between:)
extension Collection {
func split(between predicate: (Element, Element) throws -> Bool) rethrows -> [SubSequence] {
guard !isEmpty else { return [] }
var remainder = self[...]
var slices: [SubSequence] = []
for ((_, left), (index, right)) in indexed().pairs() {
if try predicate(left, right) {
slices.append(remainder.remove(upTo: index))
}
}
slices.append(remainder)
return slices
}
}
extension Collection {
func indexed() -> LazyMapCollection<Indices, (index: Index, element: Element)> {
indices.lazy.map { ($0, self[$0]) }
}
}
extension Sequence {
func pairs() -> AnyIterator<(left: Element, right: Element)> {
var iterator = makeIterator()
var previous = iterator.next()
return AnyIterator {
guard let prev = previous,
let next = iterator.next()
else { return nil }
previous = next
return (prev, next)
}
}
}
extension Collection where SubSequence == Self {
mutating func remove(upTo index: Index) -> SubSequence {
defer { self = self[index...] }
return self[..<index]
}
mutating func remove(from index: Index) -> SubSequence {
defer { self = self[..<index] }
return self[index...]
}
}
// usage:
print([1, 2, 3, 5, 6, 7, 10, 11].split(between: { $0 + 1 < $1 }))
// [ [1, 2, 3], [5, 6, 7], [10, 11] ]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment