Skip to content

Instantly share code, notes, and snippets.

@yycking
Created May 27, 2021 05:01
Show Gist options
  • Save yycking/a73cacfdbad729a69b5da7deb9b752eb to your computer and use it in GitHub Desktop.
Save yycking/a73cacfdbad729a69b5da7deb9b752eb to your computer and use it in GitHub Desktop.
Creates a sequence of pairs built out of two underlying sequences.
func combine<Sequence1, Sequence2>(_ sequence1: Sequence1, _ sequence2: Sequence2) -> CombineSequence<Sequence1, Sequence2> {
return CombineSequence(sequence1, sequence2)
}
struct CombineSequence<Sequence1: Sequence, Sequence2: Sequence> {
let _sequence1: Sequence1
let _sequence2: Sequence2
init(_ sequence1: Sequence1, _ sequence2: Sequence2) {
(_sequence1, _sequence2) = (sequence1, sequence2)
}
}
extension CombineSequence {
struct Iterator {
var _baseStream1: Sequence1.Iterator
var _baseStream2: Sequence2.Iterator
var _reachedEnd: Bool = false
init(_ iterator1: Sequence1.Iterator, _ iterator2: Sequence2.Iterator) {
(_baseStream1, _baseStream2) = (iterator1, iterator2)
}
}
}
extension CombineSequence.Iterator: IteratorProtocol {
typealias Element = (Sequence1.Element?, Sequence2.Element?)
mutating func next() -> Element? {
if _reachedEnd {
return nil
}
if let element1 = _baseStream1.next() {
if let element2 = _baseStream2.next() {
return (element1, element2)
}
return (element1, nil)
} else if let element2 = _baseStream2.next() {
return (nil, element2)
} else {
_reachedEnd = true
return nil
}
}
}
extension CombineSequence: Sequence {
typealias Element = (Sequence1.Element?, Sequence2.Element?)
func makeIterator() -> Iterator {
return Iterator(
_sequence1.makeIterator(),
_sequence2.makeIterator())
}
var underestimatedCount: Int {
return Swift.max(
_sequence1.underestimatedCount,
_sequence2.underestimatedCount
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment