Last active
November 8, 2018 21:57
-
-
Save dennisvennink/a64f6af5d846713b72effb47fa7eb9fb to your computer and use it in GitHub Desktop.
Implementations of `zipLongest(_:_:)` Without Any Custom Types
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
// Using `sequence(state:next:).lazy`. | |
func zipLongest <Sequence1: Sequence, Sequence2: Sequence> | |
(_ sequence1: Sequence1, _ sequence2: Sequence2) -> | |
LazySequence<UnfoldSequence<(Sequence1.Element?, Sequence2.Element?), | |
(Sequence1.Iterator, Sequence2.Iterator)>> { | |
return sequence(state: (sequence1.makeIterator(), sequence2.makeIterator())) { | |
let element1 = $0.0.next() | |
let element2 = $0.1.next() | |
return element1 == nil && element2 == nil ? nil : (element1, element2) | |
}.lazy | |
} |
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
// Using `AnySequence(_:).lazy`. | |
func zipLongest <Sequence1: Sequence, Sequence2: Sequence> | |
(_ sequence1: Sequence1, _ sequence2: Sequence2) -> | |
LazySequence<AnySequence<(Sequence1.Element?, Sequence2.Element?)>> { | |
var iterator1 = sequence1.makeIterator() | |
var iterator2 = sequence2.makeIterator() | |
return AnySequence { | |
AnyIterator { | |
let element1 = iterator1.next() | |
let element2 = iterator2.next() | |
return element1 == nil && element2 == nil ? nil : (element1, element2) | |
} | |
}.lazy | |
} |
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
// Using a `while` loop. | |
func zipLongest <Sequence1: Sequence, Sequence2: Sequence> | |
(_ sequence1: Sequence1, _ sequence2: Sequence2) -> | |
[(Sequence1.Element?, Sequence2.Element?)] { | |
var iterator1 = sequence1.makeIterator() | |
var iterator2 = sequence2.makeIterator() | |
var result = [(Sequence1.Element?, Sequence2.Element?)]() | |
while true { | |
let element1 = iterator1.next() | |
let element2 = iterator2.next() | |
if element1 == nil && element2 == nil { | |
break | |
} else { | |
result.append((element1, element2)) | |
} | |
} | |
return result | |
} |
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
// Using recursion. | |
func zipLongest <Sequence1: Sequence, Sequence2: Sequence> | |
(_ sequence1: Sequence1, _ sequence2: Sequence2) -> | |
[(Sequence1.Element?, Sequence2.Element?)] { | |
switch (sequence1.headTail, sequence2.headTail) { | |
case (.none, .none): return [] | |
case (.none, let .some(y, ys)): return [(nil, y)] + zipLongest([], ys) | |
case (let .some(x, xs), .none): return [(x, nil)] + zipLongest(xs, []) | |
case let (.some(x, xs), .some(y, ys)): return [(x, y)] + zipLongest(xs, ys) | |
} | |
} | |
extension Sequence { | |
var headTail: (head: Element, tail: SubSequence)? { | |
var head: Element? | |
let tail = drop { head == nil ? { head = $0 ; return true }($0) : false } | |
return head != nil ? nil : (head: head!, tail: tail) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment