Skip to content

Instantly share code, notes, and snippets.

@mattt
Last active June 16, 2019 05:53
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save mattt/73a1bb39e198a97452100943aec970ac to your computer and use it in GitHub Desktop.
Save mattt/73a1bb39e198a97452100943aec970ac to your computer and use it in GitHub Desktop.
public struct BoundedSequence<Base>: Sequence, IteratorProtocol where Base: Sequence {
public struct Boundary: Equatable {
public let isStart: Bool
public let isEnd: Bool
}
private var _iterator: Base.Iterator
private var _previous: Base.Element?
private var _current: Base.Element?
private var _next: Base.Element?
public init(_ base: Base) {
_iterator = base.makeIterator()
_next = _iterator.next()
}
public mutating func next() -> (Boundary, Base.Element)? {
(_previous, _current, _next) = (_current, _next, _iterator.next())
switch (_previous, _current, _next) {
case let (nil, element?, nil):
return (Boundary(isStart: true, isEnd: true), element)
case let (nil, element?, _):
return (Boundary(isStart: true, isEnd: false), element)
case let (_, element?, nil):
return (Boundary(isStart: false, isEnd: true), element)
case let (_, element?, _):
return (Boundary(isStart: false, isEnd: false), element)
default:
return nil
}
}
}
extension Sequence {
func bounded() -> BoundedSequence<Self> {
return BoundedSequence(self)
}
}
let array = [1, 2, 3, 4, 5]
for (boundary, element) in array.bounded() {
if boundary.isStart {
print("START")
}
print(element)
if boundary.isEnd {
print("END")
}
}
/*
Prints:
START
1
2
3
4
5
END
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment