Skip to content

Instantly share code, notes, and snippets.

@IanKeen
Created September 2, 2020 23:41
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save IanKeen/70e076e7bdc4ef73fa7e9631026a0c39 to your computer and use it in GitHub Desktop.
Save IanKeen/70e076e7bdc4ef73fa7e9631026a0c39 to your computer and use it in GitHub Desktop.
Iterate a sequence with access to the previous/next elements if they exist
/// A collection that returns the current element as well as the previous and next elements when available
public struct NeighborSequence<Base: Sequence>: Sequence {
public typealias Element = (previous: Base.Element?, current: Base.Element, next: Base.Element?)
private let base: Base
fileprivate init(_ base: Base) {
self.base = base
}
public func makeIterator() -> AnyIterator<Element> {
var iterator = base.makeIterator()
var previous: Base.Element?
var currentValue = iterator.next()
return .init {
guard let current = currentValue else { return nil }
defer { previous = current }
let next = iterator.next()
currentValue = next
return (previous, current, next)
}
}
}
extension Sequence {
/// Return `Self` as a `NeighborSequence`
///
/// Each element in a `NeighborSequence` returns the element at the specified
/// index as well as the previous and next elements when possible.
///
/// This allows you to see either side of a given element.
public var neighbors: NeighborSequence<Self> {
return .init(self)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment