Skip to content

Instantly share code, notes, and snippets.

@JadenGeller
Created May 10, 2022 02:45
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JadenGeller/8719f23ea9ce2a3e6b91ecf0528df61f to your computer and use it in GitHub Desktop.
Save JadenGeller/8719f23ea9ce2a3e6b91ecf0528df61f to your computer and use it in GitHub Desktop.
Interleave and Interpolate
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