| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490 |
- //===----------------------------------------------------------------------===//
- //
- // This source file is part of the Swift Algorithms open source project
- //
- // Copyright (c) 2020 Apple Inc. and the Swift project authors
- // Licensed under Apache License v2.0 with Runtime Library Exception
- //
- // See https://swift.org/LICENSE.txt for license information
- //
- //===----------------------------------------------------------------------===//
- //===----------------------------------------------------------------------===//
- // JoinedBySequence
- //===----------------------------------------------------------------------===//
- /// A sequence that presents the elements of a base sequence of sequences
- /// concatenated using a given separator.
- public struct JoinedBySequence<Base: Sequence, Separator: Sequence>
- where Base.Element: Sequence, Base.Element.Element == Separator.Element
- {
- @usableFromInline
- internal typealias Inner = FlattenSequence<InterspersedSequence<
- LazyMapSequence<Base, EitherSequence<Base.Element, Separator>>>>
-
- @usableFromInline
- internal let inner: Inner
-
- @inlinable
- internal init(base: Base, separator: Separator) {
- self.inner = base.lazy
- .map(EitherSequence.left)
- .interspersed(with: .right(separator))
- .joined()
- }
- }
- extension JoinedBySequence: Sequence {
- public struct Iterator: IteratorProtocol {
- @usableFromInline
- internal var inner: Inner.Iterator
-
- @inlinable
- internal init(inner: Inner.Iterator) {
- self.inner = inner
- }
-
- @inlinable
- public mutating func next() -> Base.Element.Element? {
- inner.next()
- }
- }
-
- @inlinable
- public func makeIterator() -> Iterator {
- Iterator(inner: inner.makeIterator())
- }
- }
- extension JoinedBySequence: LazySequenceProtocol
- where Base: LazySequenceProtocol {}
- //===----------------------------------------------------------------------===//
- // JoinedByClosureSequence
- //===----------------------------------------------------------------------===//
- /// A sequence that presents the elements of a base sequence of sequences
- /// concatenated using a given separator that depends on the sequences right
- /// before and after it.
- public struct JoinedByClosureSequence<Base: Sequence, Separator: Sequence>
- where Base.Element: Sequence, Base.Element.Element == Separator.Element
- {
- @usableFromInline
- internal typealias Inner = FlattenSequence<InterspersedMapSequence<
- Base, EitherSequence<Base.Element, Separator>>>
-
- @usableFromInline
- internal let inner: Inner
-
- @inlinable
- internal init(
- base: Base,
- separator: @escaping (Base.Element, Base.Element) -> Separator
- ) {
- self.inner = base.lazy
- .interspersedMap(
- EitherSequence.left,
- with: { EitherSequence.right(separator($0, $1)) })
- .joined()
- }
- }
- extension JoinedByClosureSequence: Sequence {
- public struct Iterator: IteratorProtocol {
- @usableFromInline
- internal var inner: Inner.Iterator
-
- @inlinable
- internal init(inner: Inner.Iterator) {
- self.inner = inner
- }
-
- @inlinable
- public mutating func next() -> Base.Element.Element? {
- inner.next()
- }
- }
-
- @inlinable
- public func makeIterator() -> Iterator {
- Iterator(inner: inner.makeIterator())
- }
- }
- extension JoinedByClosureSequence: LazySequenceProtocol {}
- //===----------------------------------------------------------------------===//
- // JoinedByCollection
- //===----------------------------------------------------------------------===//
- /// A collection that presents the elements of a base collection of collections
- /// concatenated using a given separator.
- public struct JoinedByCollection<Base: Collection, Separator: Collection>
- where Base.Element: Collection, Base.Element.Element == Separator.Element
- {
- @usableFromInline
- internal typealias Inner = FlattenCollection<InterspersedSequence<
- LazyMapSequence<Base, EitherSequence<Base.Element, Separator>>>>
-
- @usableFromInline
- internal let inner: Inner
-
- @inlinable
- internal init(base: Base, separator: Separator) {
- self.inner = base.lazy
- .map(EitherSequence.left)
- .interspersed(with: .right(separator))
- .joined()
- }
- }
- extension JoinedByCollection: Collection {
- public struct Index: Comparable {
- @usableFromInline
- internal let inner: Inner.Index
-
- @inlinable
- internal init(_ inner: Inner.Index) {
- self.inner = inner
- }
-
- @inlinable
- public static func == (lhs: Self, rhs: Self) -> Bool {
- lhs.inner == rhs.inner
- }
-
- @inlinable
- public static func < (lhs: Self, rhs: Self) -> Bool {
- lhs.inner < rhs.inner
- }
- }
-
- @inlinable
- public var startIndex: Index {
- Index(inner.startIndex)
- }
-
- @inlinable
- public var endIndex: Index {
- Index(inner.endIndex)
- }
-
- @inlinable
- public func index(after index: Index) -> Index {
- Index(inner.index(after: index.inner))
- }
-
- @inlinable
- public subscript(position: Index) -> Base.Element.Element {
- inner[position.inner]
- }
-
- @inlinable
- public func index(_ index: Index, offsetBy distance: Int) -> Index {
- Index(inner.index(index.inner, offsetBy: distance))
- }
-
- @inlinable
- public func index(
- _ index: Index,
- offsetBy distance: Int,
- limitedBy limit: Index
- ) -> Index? {
- inner.index(index.inner, offsetBy: distance, limitedBy: limit.inner)
- .map(Index.init)
- }
-
- @inlinable
- public func distance(from start: Index, to end: Index) -> Int {
- inner.distance(from: start.inner, to: end.inner)
- }
- }
- extension JoinedByCollection: BidirectionalCollection
- where Base: BidirectionalCollection,
- Base.Element: BidirectionalCollection,
- Separator: BidirectionalCollection
- {
- @inlinable
- public func index(before index: Index) -> Index {
- Index(inner.index(before: index.inner))
- }
- }
- extension JoinedByCollection: LazySequenceProtocol, LazyCollectionProtocol
- where Base: LazySequenceProtocol {}
- //===----------------------------------------------------------------------===//
- // JoinedByClosureCollection
- //===----------------------------------------------------------------------===//
- /// A collection that presents the elements of a base collection of collections
- /// concatenated using a given separator that depends on the collections right
- /// before and after it.
- public struct JoinedByClosureCollection<Base: Collection, Separator: Collection>
- where Base.Element: Collection, Base.Element.Element == Separator.Element
- {
- @usableFromInline
- internal typealias Inner = FlattenCollection<InterspersedMapSequence<
- Base, EitherSequence<Base.Element, Separator>>>
-
- @usableFromInline
- internal let inner: Inner
-
- @inlinable
- internal init(
- base: Base,
- separator: @escaping (Base.Element, Base.Element) -> Separator
- ) {
- self.inner = base.lazy
- .interspersedMap(
- EitherSequence.left,
- with: { EitherSequence.right(separator($0, $1)) })
- .joined()
- }
- }
- extension JoinedByClosureCollection: Collection {
- public struct Index: Comparable {
- @usableFromInline
- internal let inner: Inner.Index
-
- @inlinable
- internal init(_ inner: Inner.Index) {
- self.inner = inner
- }
-
- @inlinable
- public static func == (lhs: Self, rhs: Self) -> Bool {
- lhs.inner == rhs.inner
- }
-
- @inlinable
- public static func < (lhs: Self, rhs: Self) -> Bool {
- lhs.inner < rhs.inner
- }
- }
-
- @inlinable
- public var startIndex: Index {
- Index(inner.startIndex)
- }
-
- @inlinable
- public var endIndex: Index {
- Index(inner.endIndex)
- }
-
- @inlinable
- public func index(after index: Index) -> Index {
- Index(inner.index(after: index.inner))
- }
-
- @inlinable
- public subscript(position: Index) -> Base.Element.Element {
- inner[position.inner]
- }
-
- @inlinable
- public func index(_ index: Index, offsetBy distance: Int) -> Index {
- Index(inner.index(index.inner, offsetBy: distance))
- }
-
- @inlinable
- public func index(
- _ index: Index,
- offsetBy distance: Int,
- limitedBy limit: Index
- ) -> Index? {
- inner.index(index.inner, offsetBy: distance, limitedBy: limit.inner)
- .map(Index.init)
- }
-
- @inlinable
- public func distance(from start: Index, to end: Index) -> Int {
- inner.distance(from: start.inner, to: end.inner)
- }
- }
- extension JoinedByClosureCollection: BidirectionalCollection
- where Base: BidirectionalCollection,
- Base.Element: BidirectionalCollection,
- Separator: BidirectionalCollection
- {
- @inlinable
- public func index(before index: Index) -> Index {
- Index(inner.index(before: index.inner))
- }
- }
- extension JoinedByClosureCollection: LazyCollectionProtocol {}
- //===----------------------------------------------------------------------===//
- // Sequence.joined(by:)
- //===----------------------------------------------------------------------===//
- extension Sequence where Element: Sequence {
- /// Returns the concatenation of the elements in this sequence of sequences,
- /// inserting the given separator between each sequence.
- ///
- /// for x in [[1, 2], [3, 4], [5, 6]].joined(by: 100) {
- /// print(x)
- /// }
- /// // 1, 2, 100, 3, 4, 100, 5, 6
- @inlinable
- public func joined(by separator: Element.Element)
- -> JoinedBySequence<Self, CollectionOfOne<Element.Element>>
- {
- joined(by: CollectionOfOne(separator))
- }
-
- /// Returns the concatenation of the elements in this sequence of sequences,
- /// inserting the given separator between each sequence.
- ///
- /// for x in [[1, 2], [3, 4], [5, 6]].joined(by: [100, 200]) {
- /// print(x)
- /// }
- /// // 1, 2, 100, 200, 3, 4, 100, 200, 5, 6
- @inlinable
- public func joined<Separator>(
- by separator: Separator
- ) -> JoinedBySequence<Self, Separator>
- where Separator: Collection, Separator.Element == Element.Element
- {
- JoinedBySequence(base: self, separator: separator)
- }
-
- @inlinable
- internal func _joined(
- by update: (inout [Element.Element], Element, Element) throws -> Void
- ) rethrows -> [Element.Element] {
- var iterator = makeIterator()
- guard let first = iterator.next() else { return [] }
-
- var result = Array(first)
- var previous = first
-
- while let next = iterator.next() {
- try update(&result, previous, next)
- result.append(contentsOf: next)
- previous = next
- }
-
- return result
- }
-
- /// Returns the concatenation of the elements in this sequence of sequences,
- /// inserting the separator produced by the closure between each sequence.
- ///
- /// for x in [[1, 2], [3, 4], [5, 6]].joined(by: { $0.last! * $1.first! }) {
- /// print(x)
- /// }
- /// // 1, 2, 6, 3, 4, 20, 5, 6
- @inlinable
- public func joined(
- by separator: (Element, Element) throws -> Element.Element
- ) rethrows -> [Element.Element] {
- try _joined(by: { $0.append(try separator($1, $2)) })
- }
-
- /// Returns the concatenation of the elements in this sequence of sequences,
- /// inserting the separator produced by the closure between each sequence.
- ///
- /// for x in [[1, 2], [3, 4], [5, 6]].joined(by: { [100 * $0.last!, 100 * $1.first!] }) {
- /// print(x)
- /// }
- /// // 1, 2, 200, 300, 3, 4, 400, 500, 5, 6
- @inlinable
- public func joined<Separator>(
- by separator: (Element, Element) throws -> Separator
- ) rethrows -> [Element.Element]
- where Separator: Sequence, Separator.Element == Element.Element
- {
- try _joined(by: { $0.append(contentsOf: try separator($1, $2)) })
- }
- }
- //===----------------------------------------------------------------------===//
- // LazySequenceProtocol.joined(by:)
- //===----------------------------------------------------------------------===//
- extension LazySequenceProtocol where Element: Sequence {
- /// Returns the concatenation of the elements in this sequence of sequences,
- /// inserting the separator produced by the closure between each sequence.
- @inlinable
- public func joined(
- by separator: @escaping (Element, Element) -> Element.Element
- ) -> JoinedByClosureSequence<Elements, CollectionOfOne<Element.Element>> {
- joined(by: { CollectionOfOne(separator($0, $1)) })
- }
-
- /// Returns the concatenation of the elements in this sequence of sequences,
- /// inserting the separator produced by the closure between each sequence.
- @inlinable
- public func joined<Separator>(
- by separator: @escaping (Element, Element) -> Separator
- ) -> JoinedByClosureSequence<Elements, Separator> {
- JoinedByClosureSequence(base: elements, separator: separator)
- }
- }
- //===----------------------------------------------------------------------===//
- // Collection.joined(by:)
- //===----------------------------------------------------------------------===//
- extension Collection where Element: Collection {
- /// Returns the concatenation of the elements in this collection of
- /// collections, inserting the given separator between each collection.
- ///
- /// for x in [[1, 2], [3, 4], [5, 6]].joined(by: 100) {
- /// print(x)
- /// }
- /// // 1, 2, 100, 3, 4, 100, 5, 6
- @inlinable
- public func joined(by separator: Element.Element)
- -> JoinedByCollection<Self, CollectionOfOne<Element.Element>>
- {
- joined(by: CollectionOfOne(separator))
- }
-
- /// Returns the concatenation of the elements in this collection of
- /// collections, inserting the given separator between each collection.
- ///
- /// for x in [[1, 2], [3, 4], [5, 6]].joined(by: [100, 200]) {
- /// print(x)
- /// }
- /// // 1, 2, 100, 200, 3, 4, 100, 200, 5, 6
- @inlinable
- public func joined<Separator>(by separator: Separator)
- -> JoinedByCollection<Self, Separator>
- {
- JoinedByCollection(base: self, separator: separator)
- }
- }
- //===----------------------------------------------------------------------===//
- // LazySequenceProtocol.joined(by:) where Self: Collection
- //===----------------------------------------------------------------------===//
- extension LazySequenceProtocol where Elements: Collection, Element: Collection {
- /// Returns the concatenation of the elements in this collection of
- /// collections, inserting the separator produced by the closure between each
- /// sequence.
- @inlinable
- public func joined(
- by separator: @escaping (Element, Element) -> Element.Element
- ) -> JoinedByClosureCollection<Elements, CollectionOfOne<Element.Element>> {
- joined(by: { CollectionOfOne(separator($0, $1)) })
- }
-
- /// Returns the concatenation of the elements in this collection of
- /// collections, inserting the separator produced by the closure between each
- /// sequence.
- @inlinable
- public func joined<Separator>(
- by separator: @escaping (Element, Element) -> Separator
- ) -> JoinedByClosureCollection<Elements, Separator> {
- JoinedByClosureCollection(base: elements, separator: separator)
- }
- }
|