Created
May 10, 2022 02:45
-
-
Save JadenGeller/8719f23ea9ce2a3e6b91ecf0528df61f to your computer and use it in GitHub Desktop.
Interleave and Interpolate
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
struct Interleave<Evens: Collection, Odds: Collection> { | |
var evens: Evens | |
var odds: Odds | |
init(_ evens: Evens, _ odds: Odds) { | |
precondition(evens.count == odds.count || evens.count == odds.count + 1) | |
(self.evens, self.odds) = (evens, odds) | |
} | |
} | |
extension Interleave { | |
func mapEven<MappedEven>(_ transform: @escaping (Evens.Element) -> MappedEven) -> Interleave<LazyMapCollection<Evens, MappedEven>, Odds> { | |
.init(evens.lazy.map(transform), odds) | |
} | |
func mapOdd<MappedOdd>(_ transform: @escaping (Odds.Element) -> MappedOdd) -> Interleave<Evens, LazyMapCollection<Odds, MappedOdd>> { | |
.init(evens, odds.lazy.map(transform)) | |
} | |
} | |
extension Interleave: Sequence, Collection where Evens.Element == Odds.Element { | |
struct Index: Comparable { | |
enum Parity { case even, odd } | |
var parity: Parity | |
var evenIndex: Evens.Index | |
var oddIndex: Odds.Index | |
static func < (leading: Self, trailing: Self) -> Bool { | |
leading.evenIndex < trailing.evenIndex || leading.oddIndex < trailing.oddIndex | |
} | |
} | |
typealias Element = Evens.Element | |
var startIndex: Index { | |
.init(parity: .even, evenIndex: evens.startIndex, oddIndex: odds.startIndex) | |
} | |
var endIndex: Index { | |
.init(parity: evens.count == odds.count ? .even : .odd, evenIndex: evens.endIndex, oddIndex: odds.endIndex) | |
} | |
subscript(index: Index) -> Iterator.Element { | |
switch index.parity { | |
case .even: | |
return evens[index.evenIndex] | |
case .odd: | |
return odds[index.oddIndex] | |
} | |
} | |
func index(after i: Index) -> Index { | |
switch i.parity { | |
case .even: | |
return .init(parity: .odd, evenIndex: evens.index(after: i.evenIndex), oddIndex: i.oddIndex) | |
case .odd: | |
return .init(parity: .even, evenIndex: i.evenIndex, oddIndex: odds.index(after: i.oddIndex)) | |
} | |
} | |
} | |
extension Interleave: MutableCollection where Evens.Element == Odds.Element, Evens: MutableCollection, Odds: MutableCollection { | |
subscript(index: Index) -> Iterator.Element { | |
get { | |
switch index.parity { | |
case .even: | |
return evens[index.evenIndex] | |
case .odd: | |
return odds[index.oddIndex] | |
} | |
} | |
set { | |
switch index.parity { | |
case .even: | |
evens[index.evenIndex] = newValue | |
case .odd: | |
odds[index.oddIndex] = newValue | |
} | |
} | |
} | |
} | |
typealias Interpolate<Base: Collection, Interpolations: Collection> = Interleave<[Base.SubSequence], Interpolations> | |
extension Collection { | |
func interpolating<Interpolation>(_ interpolations: Interpolation..., isPlaceholder: (Element) -> Bool) -> Interpolate<Self, [Interpolation]> { | |
interpolating(contentsOf: interpolations, isPlaceholder: isPlaceholder) | |
} | |
func interpolating<Interpolations: Collection>(contentsOf interpolations: Interpolations, isPlaceholder: (Element) -> Bool) -> Interpolate<Self, Interpolations> { | |
.init(split(whereSeparator: isPlaceholder), interpolations) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment