Skip to content

Instantly share code, notes, and snippets.

@jandamm
Last active January 21, 2018 21:36
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jandamm/6893e27ad1516380844dc66d4eff87f2 to your computer and use it in GitHub Desktop.
Save jandamm/6893e27ad1516380844dc66d4eff87f2 to your computer and use it in GitHub Desktop.
This is a Gist for a blogpost I did.
/// In contrast to the Swift Zip2Sequence this type will not omit values that don't have a partner due to Sequence length mismatch.
/// The Iterator will iterate over `SafeZip2Sequence.Value`.
public struct SafeZip2Sequence<Sequence1: Sequence, Sequence2: Sequence> {
fileprivate let sequence1: Sequence1
fileprivate let sequence2: Sequence2
}
extension SafeZip2Sequence: Sequence {
/// An iterator for `SafeZip2Sequence`.
public struct Iterator {
fileprivate var iterator1: Sequence1.Iterator
fileprivate var iterator2: Sequence2.Iterator
}
/// An element of `SafeZip2Sequence`.
public enum Element {
case pair(first: Sequence1.Element, second: Sequence2.Element)
case first(Sequence1.Element)
case second(Sequence2.Element)
}
public func makeIterator() -> Iterator {
return Iterator(iterator1: sequence1.makeIterator(), iterator2: sequence2.makeIterator())
}
}
extension SafeZip2Sequence.Iterator: IteratorProtocol {
/// Advances to the next element and returns it, or `nil` if no next element
/// exists.
///
/// Once `nil` has been returned, all subsequent calls return `nil`.
public mutating func next() -> SafeZip2Sequence.Element? {
let value1 = iterator1.next()
let value2 = iterator2.next()
return Element(first: value1, second: value2)
}
}
fileprivate extension SafeZip2Sequence.Element {
init?(first: Sequence1.Element?, second: Sequence2.Element?) {
switch (first, second) {
case let (first?, second?):
self = .pair(first: first, second: second)
case let (first?, nil):
self = .first(first)
case let (nil, second?):
self = .second(second)
default:
return nil
}
}
}
public func safeZip<Sequence1: Sequence, Sequence2: Sequence>(_ sequence1: Sequence1, _ sequence2: Sequence2) -> SafeZip2Sequence<Sequence1, Sequence2> {
return SafeZip2Sequence(sequence1: sequence1, sequence2: sequence2)
}
public func safeZip<Sequence1, Sequence2>(_ sequence1: Sequence1, _ sequence2: Sequence2, execute: (SafeZip2Sequence<Sequence1, Sequence2>.Element) -> Void) {
for value in safeZip(sequence1, sequence2) {
execute(value)
}
}
public extension Sequence {
func mySafeZip<S: Sequence>(_ sequence: S) -> SafeZip2Sequence<Self, S> {
return safeZip(self, sequence)
}
func mySafeZip<S: Sequence>(_ sequence: S, execute: (SafeZip2Sequence<Self, S>.Element) -> Void) {
return safeZip(self, sequence, execute: execute)
}
}
public struct SafeZip2Sequence<Sequence1: Sequence, Sequence2: Sequence> {
fileprivate let sequence1: Sequence1
fileprivate let sequence2: Sequence2
}
extension SafeZip2Sequence: Sequence {
public struct Iterator {
fileprivate var iterator1: Sequence1.Iterator
fileprivate var iterator2: Sequence2.Iterator
}
}
extension SafeZip2Sequence: Sequence {
public func makeIterator() -> Iterator {
return Iterator(iterator1: sequence1.makeIterator(), iterator2: sequence2.makeIterator())
}
}
extension SafeZip2Sequence: Sequence {
public enum Element {
case pair(first: Sequence1.Element, second: Sequence2.Element)
case first(Sequence1.Element)
case second(Sequence2.Element)
}
}
extension SafeZip2Sequence.Iterator: IteratorProtocol {
public mutating func next() -> SafeZip2Sequence.Element? {
let value1 = iterator1.next()
let value2 = iterator2.next()
return Element(first: value1, second: value2)
}
}
fileprivate extension SafeZip2Sequence.Element {
init?(first: Sequence1.Element?, second: Sequence2.Element?) {
switch (first, second) {
case let (first?, second?):
self = .pair(first: first, second: second)
case let (first?, nil):
self = .first(first)
case let (nil, second?):
self = .second(second)
default:
return nil
}
}
}
public func safeZip<Sequence1: Sequence, Sequence2: Sequence>(_ sequence1: Sequence1, _ sequence2: Sequence2) -> SafeZip2Sequence<Sequence1, Sequence2> {
return SafeZip2Sequence(sequence1: sequence1, sequence2: sequence2)
}
public func safeZip<Sequence1, Sequence2>(_ sequence1: Sequence1, _ sequence2: Sequence2, execute: (SafeZip2Sequence<Sequence1, Sequence2>.Element) -> Void) {
for value in safeZip(sequence1, sequence2) {
execute(value)
}
}
for element in safeZip(labels, texts) {
print(element)
}
safeZip(labels, texts) { print($0) }
safeZip(labels, texts, execute: doSomething)
public extension Sequence {
func mySafeZip<S: Sequence>(_ sequence: S) -> SafeZip2Sequence<Self, S> {
return safeZip(self, sequence)
}
func mySafeZip<S: Sequence>(_ sequence: S, execute: (SafeZip2Sequence<Self, S>.Element) -> Void) {
return safeZip(self, sequence, execute: execute)
}
}
associatedtype Element where Self.Element == Self.Iterator.Element
associatedtype Iterator : IteratorProtocol
public func makeIterator() -> Self.Iterator
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment