Last active
July 11, 2016 15:54
-
-
Save erica/4db99d721547e8113e2fce30e0418613 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// A buffered sequence that contains all the elements of | |
/// a source sequence, with a one-element lookahead buffer | |
public struct BufferedSequence<BaseSequence : Sequence>: IteratorProtocol, Sequence { | |
internal var _base: BaseSequence | |
internal var _iterator: BaseSequence.Iterator | |
internal var bufferedElement: BaseSequence.Iterator.Element? | |
public init(_ base: BaseSequence) { | |
_base = base | |
_iterator = base.makeIterator() | |
bufferedElement = _iterator.next() | |
} | |
public mutating func next() -> BaseSequence.Iterator.Element? { | |
defer { bufferedElement = _iterator.next() ?? nil } | |
return bufferedElement | |
} | |
} | |
extension Sequence { | |
/// Returns a subsequence containing the initial elements until `predicate` | |
/// returns `false`, skipping all remaining elements | |
public func prefix(while predicate: (Self.Iterator.Element) -> Bool) -> AnyIterator<Self.Iterator.Element> { | |
var iterator = self.makeIterator() | |
return AnyIterator { | |
return iterator.next().flatMap({ return predicate($0) ? $0 : nil }) | |
} | |
} | |
/// Returns a subsequence containing the initial elements until `predicate` | |
/// returns `false`, skipping all remaining elements | |
public func drop(while predicate: (Self.Iterator.Element) -> Bool) -> AnyIterator<Self.Iterator.Element> { | |
var bufferedSequence = BufferedSequence(self) | |
while let element = bufferedSequence.bufferedElement where predicate(element) { | |
let _ = bufferedSequence.next() // drop | |
} | |
return AnyIterator(bufferedSequence) | |
} | |
} | |
/// Returns a sequence formed from `first` and repeated lazy applications of | |
/// `next` until `predicate` is false. | |
/// | |
/// The first element in the sequence is always `first`, and each successive | |
/// element is the result of invoking `next` with the previous element. The | |
/// sequence ends when `next` returns `nil`. If `next` never returns `nil`, the | |
/// sequence is infinite. | |
/// | |
/// - Parameter first: The first element to be returned from the sequence. | |
/// - Parameter next: A closure that accepts the previous sequence element and | |
/// returns the next element. | |
/// - Parameter while: A closure that accepts the previous sequence element and | |
/// returns true or false, indicating whether the sequence should continue. | |
/// - Returns: A sequence that starts with `first` and continues with every | |
/// value returned by passing the previous element to `next` until the | |
/// predicate | |
/// | |
/// - SeeAlso: `sequence(state:next:)`, `sequence(first:next:)` | |
public func sequence<T>(first: T, next: (T) -> T?, while endTest: (T) -> Bool) -> AnyIterator<T> { | |
return sequence(first: first, next: next).prefix(while: endTest) | |
} | |
// For example: prints 0...12 by 2s | |
//for i in sequence(first: 0, next: { $0 + 2 }, while: { $0 < 14 }) { | |
// print(i) | |
//} | |
// For example: prints: 10...18 by 2s | |
let s = sequence(first: 0, next: { $0 + 2 }, while: { $0 < 20 }) | |
for teenValue in s.drop(while: { $0 < 10 }) { | |
print(teenValue) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment