Skip to content

Instantly share code, notes, and snippets.

@TellowKrinkle
Last active February 4, 2019 09:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save TellowKrinkle/d4f8d95e5a273eb8e48127f4f99b2392 to your computer and use it in GitHub Desktop.
Save TellowKrinkle/d4f8d95e5a273eb8e48127f4f99b2392 to your computer and use it in GitHub Desktop.
Adjacent Pairs Sequence
public struct AdjacentPairsSequence<Base: Sequence>: Sequence {
public typealias Element = (Base.Element, Base.Element)
let base: Base
public struct Iterator: IteratorProtocol {
var last: Base.Element?
var iter: Base.Iterator
init(_ iter: Base.Iterator) {
self.iter = iter
last = self.iter.next()
}
public mutating func next() -> Element? {
guard let oldLast = last else { return nil }
last = iter.next()
guard let newLast = last else { return nil }
return (oldLast, newLast)
}
}
public __consuming func makeIterator() -> Iterator {
return Iterator(base.makeIterator())
}
public init(_ base: Base) {
self.base = base
}
}
extension AdjacentPairsSequence: Collection where Base: Collection {
public struct Index: Comparable {
public var first: Base.Index
public var second: Base.Index
public static func < (lhs: Index, rhs: Index) -> Bool {
return lhs.second < rhs.second
}
public static func == (lhs: Index, rhs: Index) -> Bool {
return lhs.second == rhs.second
}
}
public var startIndex: Index {
let first = base.startIndex
guard first != base.endIndex else { return Index(first: first, second: first) }
return Index(first: first, second: base.index(after: first))
}
public var endIndex: Index {
let end = base.endIndex
return Index(first: end, second: end)
}
public subscript(index: Index) -> Element {
return (base[index.first], base[index.second])
}
public func index(after i: Index) -> Index {
return Index(first: i.second, second: base.index(after: i.second))
}
}
extension AdjacentPairsSequence: BidirectionalCollection where Base: BidirectionalCollection {
public var endIndex: Index {
let end = base.endIndex
guard end != base.startIndex else { return Index(first: end, second: end) }
return Index(first: base.index(before: end), second: end)
}
public func index(before i: Index) -> Index {
return Index(first: base.index(before: i.first), second: i.first)
}
}
extension Sequence {
var adjacentPairs: AdjacentPairsSequence<Self> {
return AdjacentPairsSequence(self)
}
}
func printEndIndex<C: BidirectionalCollection>(_ c: C) {
print("End index as viewed from a generic function: \(c.endIndex)")
}
let col = [1, 2, 3].adjacentPairs
print("End index from a non-generic context: \(col.endIndex)")
printEndIndex(col)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment