Skip to content

Instantly share code, notes, and snippets.

@dennisvennink
Last active June 18, 2018 15:20
Show Gist options
  • Save dennisvennink/bdf3c52ae1d9a3750ec3507ab3262921 to your computer and use it in GitHub Desktop.
Save dennisvennink/bdf3c52ae1d9a3750ec3507ab3262921 to your computer and use it in GitHub Desktop.
public struct Zip <Sequence1: Sequence, Sequence2: Sequence> {
public struct ShortestSequence: Sequence {
internal let sequence1: Sequence1
internal let sequence2: Sequence2
internal init (_ sequence1: Sequence1, _ sequence2: Sequence2) {
(self.sequence1, self.sequence2) = (sequence1, sequence2)
}
public struct Iterator: IteratorProtocol {
internal var iterator1: Sequence1.Iterator
internal var iterator2: Sequence2.Iterator
internal var reachedEnd = false
internal init (_ iterator1: Sequence1.Iterator, _ iterator2: Sequence2.Iterator) {
(self.iterator1, self.iterator2) = (iterator1, iterator2)
}
public mutating func next() -> (Sequence1.Iterator.Element, Sequence2.Iterator.Element)? {
if self.reachedEnd {
return nil
}
guard let element1 = self.iterator1.next(), let element2 = self.iterator2.next() else {
self.reachedEnd.toggle()
return nil
}
return (element1, element2)
}
}
public func makeIterator () -> Iterator {
return Iterator(self.sequence1.makeIterator(), self.sequence2.makeIterator())
}
}
public struct LongestSequence: Sequence {
internal let sequence1: Sequence1
internal let sequence2: Sequence2
internal init (_ sequence1: Sequence1, _ sequence2: Sequence2) {
(self.sequence1, self.sequence2) = (sequence1, sequence2)
}
public struct Iterator: IteratorProtocol {
internal var iterator1: Sequence1.Iterator
internal var iterator2: Sequence2.Iterator
internal var reachedEnd = false
internal init (_ iterator1: Sequence1.Iterator, _ iterator2: Sequence2.Iterator) {
(self.iterator1, self.iterator2) = (iterator1, iterator2)
}
public mutating func next() -> (Sequence1.Iterator.Element?, Sequence2.Iterator.Element?)? {
if self.reachedEnd {
return nil
}
let element1 = self.iterator1.next()
let element2 = self.iterator2.next()
if element1 == nil && element2 == nil {
self.reachedEnd.toggle()
return nil
}
return (element1, element2)
}
}
public func makeIterator () -> Iterator {
return Iterator(self.sequence1.makeIterator(), self.sequence2.makeIterator())
}
}
}
public func zip <Sequence1: Sequence, Sequence2: Sequence> (_ sequence1: Sequence1, _ sequence2: Sequence2) ->
Zip<Sequence1, Sequence2>.ShortestSequence {
return Zip.ShortestSequence(sequence1, sequence2)
}
public func zipLongest <Sequence1: Sequence, Sequence2: Sequence> (_ sequence1: Sequence1, _ sequence2: Sequence2) ->
Zip<Sequence1, Sequence2>.LongestSequence {
return Zip.LongestSequence(sequence1, sequence2)
}
extension Sequence {
public func unzip <Type1, Type2> () -> ([Type1], [Type2]) where Self.Element == (Type1, Type2) {
return self.reduce(into: ([Type1](), [Type2]())) { (result, element) in
result.0.append(element.0)
result.1.append(element.1)
}
}
}
@available(*, deprecated, renamed: "Zip.ShortestSequence")
public typealias Zip2Sequence<Sequence1, Sequence2> = Zip<Sequence1, Sequence2>.ShortestSequence where
Sequence1: Sequence, Sequence2: Sequence
@available(*, deprecated, renamed: "Zip.ShortestSequence.Iterator")
public typealias Zip2Iterator<Sequence1, Sequence2> = Zip<Sequence1, Sequence2>.ShortestSequence.Iterator where
Sequence1: Sequence, Sequence2: Sequence
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment