Joined.swift 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490
  1. //===----------------------------------------------------------------------===//
  2. //
  3. // This source file is part of the Swift Algorithms open source project
  4. //
  5. // Copyright (c) 2020 Apple Inc. and the Swift project authors
  6. // Licensed under Apache License v2.0 with Runtime Library Exception
  7. //
  8. // See https://swift.org/LICENSE.txt for license information
  9. //
  10. //===----------------------------------------------------------------------===//
  11. //===----------------------------------------------------------------------===//
  12. // JoinedBySequence
  13. //===----------------------------------------------------------------------===//
  14. /// A sequence that presents the elements of a base sequence of sequences
  15. /// concatenated using a given separator.
  16. public struct JoinedBySequence<Base: Sequence, Separator: Sequence>
  17. where Base.Element: Sequence, Base.Element.Element == Separator.Element
  18. {
  19. @usableFromInline
  20. internal typealias Inner = FlattenSequence<InterspersedSequence<
  21. LazyMapSequence<Base, EitherSequence<Base.Element, Separator>>>>
  22. @usableFromInline
  23. internal let inner: Inner
  24. @inlinable
  25. internal init(base: Base, separator: Separator) {
  26. self.inner = base.lazy
  27. .map(EitherSequence.left)
  28. .interspersed(with: .right(separator))
  29. .joined()
  30. }
  31. }
  32. extension JoinedBySequence: Sequence {
  33. public struct Iterator: IteratorProtocol {
  34. @usableFromInline
  35. internal var inner: Inner.Iterator
  36. @inlinable
  37. internal init(inner: Inner.Iterator) {
  38. self.inner = inner
  39. }
  40. @inlinable
  41. public mutating func next() -> Base.Element.Element? {
  42. inner.next()
  43. }
  44. }
  45. @inlinable
  46. public func makeIterator() -> Iterator {
  47. Iterator(inner: inner.makeIterator())
  48. }
  49. }
  50. extension JoinedBySequence: LazySequenceProtocol
  51. where Base: LazySequenceProtocol {}
  52. //===----------------------------------------------------------------------===//
  53. // JoinedByClosureSequence
  54. //===----------------------------------------------------------------------===//
  55. /// A sequence that presents the elements of a base sequence of sequences
  56. /// concatenated using a given separator that depends on the sequences right
  57. /// before and after it.
  58. public struct JoinedByClosureSequence<Base: Sequence, Separator: Sequence>
  59. where Base.Element: Sequence, Base.Element.Element == Separator.Element
  60. {
  61. @usableFromInline
  62. internal typealias Inner = FlattenSequence<InterspersedMapSequence<
  63. Base, EitherSequence<Base.Element, Separator>>>
  64. @usableFromInline
  65. internal let inner: Inner
  66. @inlinable
  67. internal init(
  68. base: Base,
  69. separator: @escaping (Base.Element, Base.Element) -> Separator
  70. ) {
  71. self.inner = base.lazy
  72. .interspersedMap(
  73. EitherSequence.left,
  74. with: { EitherSequence.right(separator($0, $1)) })
  75. .joined()
  76. }
  77. }
  78. extension JoinedByClosureSequence: Sequence {
  79. public struct Iterator: IteratorProtocol {
  80. @usableFromInline
  81. internal var inner: Inner.Iterator
  82. @inlinable
  83. internal init(inner: Inner.Iterator) {
  84. self.inner = inner
  85. }
  86. @inlinable
  87. public mutating func next() -> Base.Element.Element? {
  88. inner.next()
  89. }
  90. }
  91. @inlinable
  92. public func makeIterator() -> Iterator {
  93. Iterator(inner: inner.makeIterator())
  94. }
  95. }
  96. extension JoinedByClosureSequence: LazySequenceProtocol {}
  97. //===----------------------------------------------------------------------===//
  98. // JoinedByCollection
  99. //===----------------------------------------------------------------------===//
  100. /// A collection that presents the elements of a base collection of collections
  101. /// concatenated using a given separator.
  102. public struct JoinedByCollection<Base: Collection, Separator: Collection>
  103. where Base.Element: Collection, Base.Element.Element == Separator.Element
  104. {
  105. @usableFromInline
  106. internal typealias Inner = FlattenCollection<InterspersedSequence<
  107. LazyMapSequence<Base, EitherSequence<Base.Element, Separator>>>>
  108. @usableFromInline
  109. internal let inner: Inner
  110. @inlinable
  111. internal init(base: Base, separator: Separator) {
  112. self.inner = base.lazy
  113. .map(EitherSequence.left)
  114. .interspersed(with: .right(separator))
  115. .joined()
  116. }
  117. }
  118. extension JoinedByCollection: Collection {
  119. public struct Index: Comparable {
  120. @usableFromInline
  121. internal let inner: Inner.Index
  122. @inlinable
  123. internal init(_ inner: Inner.Index) {
  124. self.inner = inner
  125. }
  126. @inlinable
  127. public static func == (lhs: Self, rhs: Self) -> Bool {
  128. lhs.inner == rhs.inner
  129. }
  130. @inlinable
  131. public static func < (lhs: Self, rhs: Self) -> Bool {
  132. lhs.inner < rhs.inner
  133. }
  134. }
  135. @inlinable
  136. public var startIndex: Index {
  137. Index(inner.startIndex)
  138. }
  139. @inlinable
  140. public var endIndex: Index {
  141. Index(inner.endIndex)
  142. }
  143. @inlinable
  144. public func index(after index: Index) -> Index {
  145. Index(inner.index(after: index.inner))
  146. }
  147. @inlinable
  148. public subscript(position: Index) -> Base.Element.Element {
  149. inner[position.inner]
  150. }
  151. @inlinable
  152. public func index(_ index: Index, offsetBy distance: Int) -> Index {
  153. Index(inner.index(index.inner, offsetBy: distance))
  154. }
  155. @inlinable
  156. public func index(
  157. _ index: Index,
  158. offsetBy distance: Int,
  159. limitedBy limit: Index
  160. ) -> Index? {
  161. inner.index(index.inner, offsetBy: distance, limitedBy: limit.inner)
  162. .map(Index.init)
  163. }
  164. @inlinable
  165. public func distance(from start: Index, to end: Index) -> Int {
  166. inner.distance(from: start.inner, to: end.inner)
  167. }
  168. }
  169. extension JoinedByCollection: BidirectionalCollection
  170. where Base: BidirectionalCollection,
  171. Base.Element: BidirectionalCollection,
  172. Separator: BidirectionalCollection
  173. {
  174. @inlinable
  175. public func index(before index: Index) -> Index {
  176. Index(inner.index(before: index.inner))
  177. }
  178. }
  179. extension JoinedByCollection: LazySequenceProtocol, LazyCollectionProtocol
  180. where Base: LazySequenceProtocol {}
  181. //===----------------------------------------------------------------------===//
  182. // JoinedByClosureCollection
  183. //===----------------------------------------------------------------------===//
  184. /// A collection that presents the elements of a base collection of collections
  185. /// concatenated using a given separator that depends on the collections right
  186. /// before and after it.
  187. public struct JoinedByClosureCollection<Base: Collection, Separator: Collection>
  188. where Base.Element: Collection, Base.Element.Element == Separator.Element
  189. {
  190. @usableFromInline
  191. internal typealias Inner = FlattenCollection<InterspersedMapSequence<
  192. Base, EitherSequence<Base.Element, Separator>>>
  193. @usableFromInline
  194. internal let inner: Inner
  195. @inlinable
  196. internal init(
  197. base: Base,
  198. separator: @escaping (Base.Element, Base.Element) -> Separator
  199. ) {
  200. self.inner = base.lazy
  201. .interspersedMap(
  202. EitherSequence.left,
  203. with: { EitherSequence.right(separator($0, $1)) })
  204. .joined()
  205. }
  206. }
  207. extension JoinedByClosureCollection: Collection {
  208. public struct Index: Comparable {
  209. @usableFromInline
  210. internal let inner: Inner.Index
  211. @inlinable
  212. internal init(_ inner: Inner.Index) {
  213. self.inner = inner
  214. }
  215. @inlinable
  216. public static func == (lhs: Self, rhs: Self) -> Bool {
  217. lhs.inner == rhs.inner
  218. }
  219. @inlinable
  220. public static func < (lhs: Self, rhs: Self) -> Bool {
  221. lhs.inner < rhs.inner
  222. }
  223. }
  224. @inlinable
  225. public var startIndex: Index {
  226. Index(inner.startIndex)
  227. }
  228. @inlinable
  229. public var endIndex: Index {
  230. Index(inner.endIndex)
  231. }
  232. @inlinable
  233. public func index(after index: Index) -> Index {
  234. Index(inner.index(after: index.inner))
  235. }
  236. @inlinable
  237. public subscript(position: Index) -> Base.Element.Element {
  238. inner[position.inner]
  239. }
  240. @inlinable
  241. public func index(_ index: Index, offsetBy distance: Int) -> Index {
  242. Index(inner.index(index.inner, offsetBy: distance))
  243. }
  244. @inlinable
  245. public func index(
  246. _ index: Index,
  247. offsetBy distance: Int,
  248. limitedBy limit: Index
  249. ) -> Index? {
  250. inner.index(index.inner, offsetBy: distance, limitedBy: limit.inner)
  251. .map(Index.init)
  252. }
  253. @inlinable
  254. public func distance(from start: Index, to end: Index) -> Int {
  255. inner.distance(from: start.inner, to: end.inner)
  256. }
  257. }
  258. extension JoinedByClosureCollection: BidirectionalCollection
  259. where Base: BidirectionalCollection,
  260. Base.Element: BidirectionalCollection,
  261. Separator: BidirectionalCollection
  262. {
  263. @inlinable
  264. public func index(before index: Index) -> Index {
  265. Index(inner.index(before: index.inner))
  266. }
  267. }
  268. extension JoinedByClosureCollection: LazyCollectionProtocol {}
  269. //===----------------------------------------------------------------------===//
  270. // Sequence.joined(by:)
  271. //===----------------------------------------------------------------------===//
  272. extension Sequence where Element: Sequence {
  273. /// Returns the concatenation of the elements in this sequence of sequences,
  274. /// inserting the given separator between each sequence.
  275. ///
  276. /// for x in [[1, 2], [3, 4], [5, 6]].joined(by: 100) {
  277. /// print(x)
  278. /// }
  279. /// // 1, 2, 100, 3, 4, 100, 5, 6
  280. @inlinable
  281. public func joined(by separator: Element.Element)
  282. -> JoinedBySequence<Self, CollectionOfOne<Element.Element>>
  283. {
  284. joined(by: CollectionOfOne(separator))
  285. }
  286. /// Returns the concatenation of the elements in this sequence of sequences,
  287. /// inserting the given separator between each sequence.
  288. ///
  289. /// for x in [[1, 2], [3, 4], [5, 6]].joined(by: [100, 200]) {
  290. /// print(x)
  291. /// }
  292. /// // 1, 2, 100, 200, 3, 4, 100, 200, 5, 6
  293. @inlinable
  294. public func joined<Separator>(
  295. by separator: Separator
  296. ) -> JoinedBySequence<Self, Separator>
  297. where Separator: Collection, Separator.Element == Element.Element
  298. {
  299. JoinedBySequence(base: self, separator: separator)
  300. }
  301. @inlinable
  302. internal func _joined(
  303. by update: (inout [Element.Element], Element, Element) throws -> Void
  304. ) rethrows -> [Element.Element] {
  305. var iterator = makeIterator()
  306. guard let first = iterator.next() else { return [] }
  307. var result = Array(first)
  308. var previous = first
  309. while let next = iterator.next() {
  310. try update(&result, previous, next)
  311. result.append(contentsOf: next)
  312. previous = next
  313. }
  314. return result
  315. }
  316. /// Returns the concatenation of the elements in this sequence of sequences,
  317. /// inserting the separator produced by the closure between each sequence.
  318. ///
  319. /// for x in [[1, 2], [3, 4], [5, 6]].joined(by: { $0.last! * $1.first! }) {
  320. /// print(x)
  321. /// }
  322. /// // 1, 2, 6, 3, 4, 20, 5, 6
  323. @inlinable
  324. public func joined(
  325. by separator: (Element, Element) throws -> Element.Element
  326. ) rethrows -> [Element.Element] {
  327. try _joined(by: { $0.append(try separator($1, $2)) })
  328. }
  329. /// Returns the concatenation of the elements in this sequence of sequences,
  330. /// inserting the separator produced by the closure between each sequence.
  331. ///
  332. /// for x in [[1, 2], [3, 4], [5, 6]].joined(by: { [100 * $0.last!, 100 * $1.first!] }) {
  333. /// print(x)
  334. /// }
  335. /// // 1, 2, 200, 300, 3, 4, 400, 500, 5, 6
  336. @inlinable
  337. public func joined<Separator>(
  338. by separator: (Element, Element) throws -> Separator
  339. ) rethrows -> [Element.Element]
  340. where Separator: Sequence, Separator.Element == Element.Element
  341. {
  342. try _joined(by: { $0.append(contentsOf: try separator($1, $2)) })
  343. }
  344. }
  345. //===----------------------------------------------------------------------===//
  346. // LazySequenceProtocol.joined(by:)
  347. //===----------------------------------------------------------------------===//
  348. extension LazySequenceProtocol where Element: Sequence {
  349. /// Returns the concatenation of the elements in this sequence of sequences,
  350. /// inserting the separator produced by the closure between each sequence.
  351. @inlinable
  352. public func joined(
  353. by separator: @escaping (Element, Element) -> Element.Element
  354. ) -> JoinedByClosureSequence<Elements, CollectionOfOne<Element.Element>> {
  355. joined(by: { CollectionOfOne(separator($0, $1)) })
  356. }
  357. /// Returns the concatenation of the elements in this sequence of sequences,
  358. /// inserting the separator produced by the closure between each sequence.
  359. @inlinable
  360. public func joined<Separator>(
  361. by separator: @escaping (Element, Element) -> Separator
  362. ) -> JoinedByClosureSequence<Elements, Separator> {
  363. JoinedByClosureSequence(base: elements, separator: separator)
  364. }
  365. }
  366. //===----------------------------------------------------------------------===//
  367. // Collection.joined(by:)
  368. //===----------------------------------------------------------------------===//
  369. extension Collection where Element: Collection {
  370. /// Returns the concatenation of the elements in this collection of
  371. /// collections, inserting the given separator between each collection.
  372. ///
  373. /// for x in [[1, 2], [3, 4], [5, 6]].joined(by: 100) {
  374. /// print(x)
  375. /// }
  376. /// // 1, 2, 100, 3, 4, 100, 5, 6
  377. @inlinable
  378. public func joined(by separator: Element.Element)
  379. -> JoinedByCollection<Self, CollectionOfOne<Element.Element>>
  380. {
  381. joined(by: CollectionOfOne(separator))
  382. }
  383. /// Returns the concatenation of the elements in this collection of
  384. /// collections, inserting the given separator between each collection.
  385. ///
  386. /// for x in [[1, 2], [3, 4], [5, 6]].joined(by: [100, 200]) {
  387. /// print(x)
  388. /// }
  389. /// // 1, 2, 100, 200, 3, 4, 100, 200, 5, 6
  390. @inlinable
  391. public func joined<Separator>(by separator: Separator)
  392. -> JoinedByCollection<Self, Separator>
  393. {
  394. JoinedByCollection(base: self, separator: separator)
  395. }
  396. }
  397. //===----------------------------------------------------------------------===//
  398. // LazySequenceProtocol.joined(by:) where Self: Collection
  399. //===----------------------------------------------------------------------===//
  400. extension LazySequenceProtocol where Elements: Collection, Element: Collection {
  401. /// Returns the concatenation of the elements in this collection of
  402. /// collections, inserting the separator produced by the closure between each
  403. /// sequence.
  404. @inlinable
  405. public func joined(
  406. by separator: @escaping (Element, Element) -> Element.Element
  407. ) -> JoinedByClosureCollection<Elements, CollectionOfOne<Element.Element>> {
  408. joined(by: { CollectionOfOne(separator($0, $1)) })
  409. }
  410. /// Returns the concatenation of the elements in this collection of
  411. /// collections, inserting the separator produced by the closure between each
  412. /// sequence.
  413. @inlinable
  414. public func joined<Separator>(
  415. by separator: @escaping (Element, Element) -> Separator
  416. ) -> JoinedByClosureCollection<Elements, Separator> {
  417. JoinedByClosureCollection(base: elements, separator: separator)
  418. }
  419. }