Split.swift 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757
  1. //===----------------------------------------------------------------------===//
  2. //
  3. // This source file is part of the Swift Algorithms open source project
  4. //
  5. // Copyright (c) 2021 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. // SplitSequence
  13. //===----------------------------------------------------------------------===//
  14. /// A sequence that lazily splits a base sequence into subsequences separated by
  15. /// elements that satisfy the given `whereSeparator` predicate.
  16. ///
  17. /// - Note: This type is the result of
  18. ///
  19. /// x.split(maxSplits:omittingEmptySubsequences:whereSeparator)
  20. /// x.split(separator:maxSplits:omittingEmptySubsequences)
  21. ///
  22. /// where `x` conforms to `LazySequenceProtocol`.
  23. public struct SplitSequence<Base: Sequence> {
  24. @usableFromInline
  25. internal let base: Base
  26. @usableFromInline
  27. internal let isSeparator: (Base.Element) -> Bool
  28. @usableFromInline
  29. internal let maxSplits: Int
  30. @usableFromInline
  31. internal let omittingEmptySubsequences: Bool
  32. @inlinable
  33. internal init(
  34. base: Base,
  35. isSeparator: @escaping (Base.Element) -> Bool,
  36. maxSplits: Int,
  37. omittingEmptySubsequences: Bool
  38. ) {
  39. self.base = base
  40. self.isSeparator = isSeparator
  41. self.maxSplits = maxSplits
  42. self.omittingEmptySubsequences = omittingEmptySubsequences
  43. }
  44. }
  45. extension SplitSequence: Sequence {
  46. public struct Iterator {
  47. public typealias Element = [Base.Element]
  48. @usableFromInline
  49. internal var base: Base.Iterator
  50. @usableFromInline
  51. internal let isSeparator: (Base.Element) -> Bool
  52. @usableFromInline
  53. internal let maxSplits: Int
  54. @usableFromInline
  55. internal let omittingEmptySubsequences: Bool
  56. /// The number of splits performed.
  57. @usableFromInline
  58. internal var splitCount = 0
  59. /// The number of subsequences returned.
  60. @usableFromInline
  61. internal var sequenceLength = 0
  62. @inlinable
  63. internal init(
  64. base: Base.Iterator,
  65. whereSeparator: @escaping (Base.Element) -> Bool,
  66. maxSplits: Int,
  67. omittingEmptySubsequences: Bool
  68. ) {
  69. self.base = base
  70. self.isSeparator = whereSeparator
  71. self.maxSplits = maxSplits
  72. self.omittingEmptySubsequences = omittingEmptySubsequences
  73. }
  74. }
  75. @inlinable
  76. public func makeIterator() -> Iterator {
  77. Iterator(
  78. base: base.makeIterator(),
  79. whereSeparator: self.isSeparator,
  80. maxSplits: self.maxSplits,
  81. omittingEmptySubsequences: self.omittingEmptySubsequences
  82. )
  83. }
  84. }
  85. extension SplitSequence.Iterator: IteratorProtocol {
  86. @inlinable
  87. public mutating func next() -> Element? {
  88. var currentElement = base.next()
  89. var subsequence: Element = []
  90. // Add the next elements of the base sequence to this subsequence, until we
  91. // reach a separator, unless we've already split the maximum number of
  92. // times. In all cases, stop at the end of the base sequence.
  93. while currentElement != nil {
  94. if splitCount < maxSplits && isSeparator(currentElement!) {
  95. if omittingEmptySubsequences && subsequence.isEmpty {
  96. // Keep going if we don't want to return an empty subsequence.
  97. currentElement = base.next()
  98. continue
  99. } else {
  100. splitCount += 1
  101. break
  102. }
  103. } else {
  104. subsequence.append(currentElement!)
  105. currentElement = base.next()
  106. }
  107. }
  108. // We're done iterating when we've reached the end of the base sequence,
  109. // and we've either returned the maximum number of subsequences (one more
  110. // than the number of separators), or the only subsequence left to return is
  111. // empty and we're omitting those.
  112. if currentElement == nil
  113. && (sequenceLength == splitCount + 1
  114. || omittingEmptySubsequences && subsequence.isEmpty)
  115. {
  116. return nil
  117. } else {
  118. sequenceLength += 1
  119. return subsequence
  120. }
  121. }
  122. }
  123. extension SplitSequence: LazySequenceProtocol {}
  124. extension LazySequenceProtocol {
  125. /// Lazily returns the longest possible subsequences of the sequence, in
  126. /// order, that don't contain elements satisfying the given predicate.
  127. ///
  128. /// The resulting lazy sequence consists of at most `maxSplits + 1`
  129. /// subsequences. Elements that are used to split the sequence are not
  130. /// returned as part of any subsequence (except possibly the last one, in the
  131. /// case where `maxSplits` is less than the number of separators in the
  132. /// sequence).
  133. ///
  134. /// The following examples show the effects of the `maxSplits` and
  135. /// `omittingEmptySubsequences` parameters when lazily splitting a sequence of
  136. /// integers using a closure that matches numbers evenly divisible by 3 or 5.
  137. /// The first use of `split` returns each subsequence that was originally
  138. /// separated by one or more such numbers.
  139. ///
  140. /// let numbers = stride(from: 1, through: 16, by: 1)
  141. /// for subsequence in numbers.lazy.split(
  142. /// whereSeparator: { $0 % 3 == 0 || $0 % 5 == 0 }
  143. /// ) {
  144. /// print(subsequence)
  145. /// }
  146. /// /* Prints:
  147. /// [1, 2]
  148. /// [4]
  149. /// [7, 8]
  150. /// [11]
  151. /// [13, 14]
  152. /// [16]
  153. /// */
  154. ///
  155. /// The second example passes `1` for the `maxSplits` parameter, so the
  156. /// original sequence is split just once, into two subsequences.
  157. ///
  158. /// for subsequence in numbers.lazy.split(
  159. /// maxSplits: 1,
  160. /// whereSeparator: { $0 % 3 == 0 || $0 % 5 == 0 }
  161. /// ) {
  162. /// print(subsequence)
  163. /// }
  164. /// /* Prints:
  165. /// [1, 2]
  166. /// [4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
  167. /// */
  168. ///
  169. /// The final example passes `false` for the `omittingEmptySubsequences`
  170. /// parameter, so the sequence of returned subsequences contains empty
  171. /// subsequences where numbers evenly divisible by 3 or 5 were repeated.
  172. ///
  173. /// for subsequence in numbers.lazy.split(
  174. /// omittingEmptySubsequences: false,
  175. /// whereSeparator: { $0 % 3 == 0 || $0 % 5 == 0 }
  176. /// ) {
  177. /// print(subsequence)
  178. /// }
  179. /// /* Prints:
  180. /// [1, 2]
  181. /// [4]
  182. /// []
  183. /// [7, 8]
  184. /// []
  185. /// [11]
  186. /// [13, 14]
  187. /// [16]
  188. /// */
  189. ///
  190. /// - Parameters:
  191. /// - maxSplits: The maximum number of times to split the sequence, or
  192. /// one less than the number of subsequences to return. If
  193. /// `maxSplits + 1` subsequences are returned, the last one is a suffix
  194. /// of the original sequence containing the remaining elements.
  195. /// `maxSplits` must be greater than or equal to zero. The default value
  196. /// is `Int.max`.
  197. /// - omittingEmptySubsequences: If `false`, an empty subsequence is
  198. /// returned in the result for each pair of consecutive elements
  199. /// satisfying the `isSeparator` predicate and for each element at the
  200. /// start or end of the sequence satisfying the `isSeparator`
  201. /// predicate. The default value is `true`.
  202. /// - whereSeparator: A closure that takes an element as an argument and
  203. /// returns a Boolean value indicating whether the sequence should be
  204. /// split at that element.
  205. /// - Returns: A lazy sequence of subsequences, split from this sequence's
  206. /// elements.
  207. ///
  208. /// - Complexity: O(*n*), where *n* is the length of the sequence.
  209. @inlinable
  210. public func split(
  211. maxSplits: Int = Int.max,
  212. omittingEmptySubsequences: Bool = true,
  213. whereSeparator isSeparator: @escaping (Element) -> Bool
  214. ) -> SplitSequence<Elements> {
  215. precondition(maxSplits >= 0, "Must take zero or more splits")
  216. return SplitSequence(
  217. base: elements,
  218. isSeparator: isSeparator,
  219. maxSplits: maxSplits,
  220. omittingEmptySubsequences: omittingEmptySubsequences
  221. )
  222. }
  223. }
  224. extension LazySequenceProtocol where Element: Equatable {
  225. /// Lazily returns the longest possible subsequences of the sequence, in
  226. /// order, around elements equal to the given element.
  227. ///
  228. /// The resulting lazy sequence consists of at most `maxSplits + 1`
  229. /// subsequences. Elements that are used to split the sequence are not
  230. /// returned as part of any subsequence (except possibly the last one, in the
  231. /// case where `maxSplits` is less than the number of separators in the
  232. /// sequence).
  233. ///
  234. /// The following examples show the effects of the `maxSplits` and
  235. /// `omittingEmptySubsequences` parameters when splitting a sequence of
  236. /// integers at each zero (`0`). The first use of `split` returns each
  237. /// subsequence that was originally separated by one or more zeros.
  238. ///
  239. /// let numbers = AnySequence([1, 2, 0, 3, 4, 0, 0, 5])
  240. /// for subsequence in numbers.lazy.split(separator: 0) {
  241. /// print(subsequence)
  242. /// }
  243. /// /* Prints:
  244. /// [1, 2]
  245. /// [3, 4]
  246. /// [5]
  247. /// */
  248. ///
  249. /// The second example passes `1` for the `maxSplits` parameter, so the
  250. /// original sequence is split just once, into two subsequences.
  251. ///
  252. /// for subsequence in numbers.lazy.split(
  253. /// separator: 0,
  254. /// maxSplits: 1
  255. /// ) {
  256. /// print(subsequence)
  257. /// }
  258. /// /* Prints:
  259. /// [1, 2]
  260. /// [3, 4, 0, 0, 5]
  261. /// */
  262. ///
  263. /// The final example passes `false` for the `omittingEmptySubsequences`
  264. /// parameter, so the sequence of returned subsequences contains empty
  265. /// subsequences where zeros were repeated.
  266. ///
  267. /// for subsequence in numbers.lazy.split(
  268. /// separator: 0,
  269. /// omittingEmptySubsequences: false
  270. /// ) {
  271. /// print(subsequence)
  272. /// }
  273. /// /* Prints:
  274. /// [1, 2]
  275. /// [3, 4]
  276. /// []
  277. /// [5]
  278. /// */
  279. ///
  280. /// - Parameters:
  281. /// - separator: The element that should be split upon.
  282. /// - maxSplits: The maximum number of times to split the sequence, or
  283. /// one less than the number of subsequences to return. If
  284. /// `maxSplits + 1` subsequences are returned, the last one is a suffix
  285. /// of the original sequence containing the remaining elements.
  286. /// `maxSplits` must be greater than or equal to zero. The default value
  287. /// is `Int.max`.
  288. /// - omittingEmptySubsequences: If `false`, an empty subsequence is
  289. /// returned in the result for each consecutive pair of `separator`
  290. /// elements in the sequence and for each instance of `separator` at
  291. /// the start or end of the sequence. If `true`, only nonempty
  292. /// subsequences are returned. The default value is `true`.
  293. /// - Returns: A lazy sequence of subsequences, split from this sequence's
  294. /// elements.
  295. ///
  296. /// - Complexity: O(*n*), where *n* is the length of the sequence.
  297. @inlinable
  298. public func split(
  299. separator: Element,
  300. maxSplits: Int = Int.max,
  301. omittingEmptySubsequences: Bool = true
  302. ) -> SplitSequence<Elements> {
  303. precondition(maxSplits >= 0, "Must take zero or more splits")
  304. return SplitSequence(
  305. base: elements,
  306. isSeparator: { $0 == separator },
  307. maxSplits: maxSplits,
  308. omittingEmptySubsequences: omittingEmptySubsequences
  309. )
  310. }
  311. }
  312. //===----------------------------------------------------------------------===//
  313. // SplitCollection
  314. //===----------------------------------------------------------------------===//
  315. /// A collection that lazily splits a base collection into subsequences
  316. /// separated by elements that satisfy the given `whereSeparator` predicate.
  317. ///
  318. /// - Note: This type is the result of
  319. ///
  320. /// x.split(maxSplits:omittingEmptySubsequences:whereSeparator)
  321. /// x.split(separator:maxSplits:omittingEmptySubsequences)
  322. ///
  323. /// where `x` conforms to `LazySequenceProtocol` and `Collection`.
  324. public struct SplitCollection<Base: Collection> {
  325. @usableFromInline
  326. internal let base: Base
  327. @usableFromInline
  328. internal let isSeparator: (Base.Element) -> Bool
  329. @usableFromInline
  330. internal let maxSplits: Int
  331. @usableFromInline
  332. internal let omittingEmptySubsequences: Bool
  333. @usableFromInline
  334. internal var _startIndex: Index
  335. @inlinable
  336. internal init(
  337. base: Base,
  338. isSeparator: @escaping (Base.Element) -> Bool,
  339. maxSplits: Int,
  340. omittingEmptySubsequences: Bool
  341. ) {
  342. self.base = base
  343. self.isSeparator = isSeparator
  344. self.maxSplits = maxSplits
  345. self.omittingEmptySubsequences = omittingEmptySubsequences
  346. // We precalculate `startIndex`. There are three possibilities:
  347. // 1. `base` is empty and we're _not_ omitting empty subsequences, in which
  348. // case the following index describes the sole element of this collection;
  349. self._startIndex = Index(
  350. baseRange: base.startIndex..<base.startIndex,
  351. sequenceLength: 1,
  352. splitCount: 0
  353. )
  354. if base.isEmpty {
  355. if omittingEmptySubsequences {
  356. // 2. `base` is empty and we _are_ omitting empty subsequences, so this
  357. // collection has no elements;
  358. _startIndex = endIndex
  359. }
  360. } else {
  361. // 3. `base` isn't empty, so we must iterate it to determine the start
  362. // index.
  363. _startIndex = indexForSubsequence(
  364. atOrAfter: base.startIndex,
  365. sequenceLength: 0,
  366. splitCount: 0
  367. )
  368. }
  369. }
  370. }
  371. extension SplitCollection: Collection {
  372. /// Position of a subsequence in a split collection.
  373. public struct Index: Comparable {
  374. /// The range corresponding to the subsequence at this position.
  375. @usableFromInline
  376. internal let baseRange: Range<Base.Index>
  377. /// The number of subsequences up to and including this position in the
  378. /// collection.
  379. @usableFromInline
  380. internal let sequenceLength: Int
  381. /// The number splits performed up to and including this position in the
  382. /// collection.
  383. @usableFromInline
  384. internal let splitCount: Int
  385. @inlinable
  386. internal init(
  387. baseRange: Range<Base.Index>,
  388. sequenceLength: Int,
  389. splitCount: Int
  390. ) {
  391. self.baseRange = baseRange
  392. self.sequenceLength = sequenceLength
  393. self.splitCount = splitCount
  394. }
  395. @inlinable
  396. public static func == (lhs: Index, rhs: Index) -> Bool {
  397. // `sequenceLength` is equivalent to the index's 1-based position in the
  398. // collection of indices.
  399. lhs.sequenceLength == rhs.sequenceLength
  400. }
  401. @inlinable
  402. public static func < (lhs: Index, rhs: Index) -> Bool {
  403. lhs.sequenceLength < rhs.sequenceLength
  404. }
  405. }
  406. /// Returns the index of the subsequence starting at or after the given base
  407. /// collection index.
  408. @inlinable
  409. internal func indexForSubsequence(
  410. atOrAfter lowerBound: Base.Index,
  411. sequenceLength: Int,
  412. splitCount: Int
  413. ) -> Index {
  414. var start = lowerBound
  415. // If we don't have any more splits to do (which we'll determine shortly),
  416. // the end of this subsequence will be the end of the base collection.
  417. var end = base.endIndex
  418. if splitCount < maxSplits {
  419. // The non-inclusive end of this subsequence is marked by the next
  420. // separator, or the end of the base collection.
  421. end =
  422. base[start...].firstIndex(where: isSeparator)
  423. ?? base.endIndex
  424. if base[start..<end].isEmpty {
  425. if omittingEmptySubsequences {
  426. // Find the next subsequence of non-separators.
  427. start =
  428. base[end...].firstIndex(where: { !isSeparator($0) })
  429. ?? base.endIndex
  430. if start == base.endIndex {
  431. // No non-separators left in the base collection. We're done.
  432. return endIndex
  433. }
  434. end = base[start...].firstIndex(where: isSeparator) ?? base.endIndex
  435. }
  436. }
  437. }
  438. var updatedSplitCount = splitCount
  439. if end != base.endIndex {
  440. // This subsequence ends on a separator (and perhaps includes other
  441. // separators, if we're omitting empty subsequences), so we've performed
  442. // another split.
  443. updatedSplitCount += 1
  444. }
  445. return Index(
  446. baseRange: start..<end,
  447. sequenceLength: sequenceLength + 1,
  448. splitCount: updatedSplitCount
  449. )
  450. }
  451. @inlinable
  452. public var startIndex: Index {
  453. _startIndex
  454. }
  455. @inlinable
  456. public var endIndex: Index {
  457. Index(
  458. baseRange: base.endIndex..<base.endIndex,
  459. sequenceLength: Int.max,
  460. splitCount: Int.max
  461. )
  462. }
  463. @inlinable
  464. public func index(after i: Index) -> Index {
  465. precondition(i != endIndex, "Can't advance past endIndex")
  466. var subsequenceStart = i.baseRange.upperBound
  467. if subsequenceStart < base.endIndex {
  468. // If we're not already at the end of the base collection, the previous
  469. // susequence ended with a separator. Start searching for the next
  470. // subsequence at the following element.
  471. subsequenceStart = base.index(after: i.baseRange.upperBound)
  472. }
  473. guard subsequenceStart != base.endIndex else {
  474. if !omittingEmptySubsequences
  475. && i.sequenceLength < i.splitCount + 1
  476. {
  477. // The base collection ended with a separator, so we need to emit one
  478. // more empty subsequence. This one differs from `endIndex` in its
  479. // `sequenceLength` (except in an extreme edge case!), which is the
  480. // sole property tested for equality and comparison.
  481. return Index(
  482. baseRange: base.endIndex..<base.endIndex,
  483. sequenceLength: i.sequenceLength + 1,
  484. splitCount: i.splitCount
  485. )
  486. } else {
  487. return endIndex
  488. }
  489. }
  490. return indexForSubsequence(
  491. atOrAfter: subsequenceStart,
  492. sequenceLength: i.sequenceLength,
  493. splitCount: i.splitCount
  494. )
  495. }
  496. @inlinable
  497. public subscript(position: Index) -> Base.SubSequence {
  498. precondition(position != endIndex, "Can't subscript using endIndex")
  499. return base[position.baseRange]
  500. }
  501. }
  502. extension SplitCollection.Index: Hashable {
  503. @inlinable
  504. public func hash(into hasher: inout Hasher) {
  505. hasher.combine(sequenceLength)
  506. }
  507. }
  508. extension SplitCollection: LazyCollectionProtocol {}
  509. extension LazySequenceProtocol where Self: Collection, Elements: Collection {
  510. /// Lazily returns the longest possible subsequences of the collection, in
  511. /// order, that don't contain elements satisfying the given predicate.
  512. ///
  513. /// The resulting lazy collection consists of at most `maxSplits + 1`
  514. /// subsequences. Elements that are used to split the collection are not
  515. /// returned as part of any subsequence (except possibly the last one, in the
  516. /// case where `maxSplits` is less than the number of separators in the
  517. /// collection).
  518. ///
  519. /// The following examples show the effects of the `maxSplits` and
  520. /// `omittingEmptySubsequences` parameters when lazily splitting a string
  521. /// using a closure that matches spaces. The first use of `split` returns each
  522. /// word that was originally separated by one or more spaces.
  523. ///
  524. /// let line = "BLANCHE: I don't want realism. I want magic!"
  525. /// for spaceless in line.lazy.split(whereSeparator: { $0 == " " }) {
  526. /// print(spaceless)
  527. /// }
  528. /// // Prints
  529. /// // BLANCHE:
  530. /// // I
  531. /// // don't
  532. /// // want
  533. /// // realism.
  534. /// // I
  535. /// // want
  536. /// // magic!
  537. ///
  538. /// The second example passes `1` for the `maxSplits` parameter, so the
  539. /// original string is split just once, into two new strings.
  540. ///
  541. /// for spaceless in line.lazy.split(
  542. /// maxSplits: 1,
  543. /// whereSeparator: { $0 == " " }
  544. /// ) {
  545. /// print(spaceless)
  546. /// }
  547. /// // Prints
  548. /// // BLANCHE:
  549. /// // I don't want realism. I want magic!
  550. ///
  551. /// The final example passes `false` for the `omittingEmptySubsequences`
  552. /// parameter, so the returned array contains empty strings where spaces
  553. /// were repeated.
  554. ///
  555. /// for spaceless in line.lazy.split(
  556. /// omittingEmptySubsequences: false,
  557. /// whereSeparator: { $0 == " " }
  558. /// ) {
  559. /// print(spaceless)
  560. /// }
  561. /// // Prints
  562. /// // BLANCHE:
  563. /// //
  564. /// //
  565. /// // I
  566. /// // don't
  567. /// // want
  568. /// // realism.
  569. /// // I
  570. /// // want
  571. /// // magic!
  572. ///
  573. /// - Parameters:
  574. /// - maxSplits: The maximum number of times to split the collection, or
  575. /// one less than the number of subsequences to return. If
  576. /// `maxSplits + 1` subsequences are returned, the last one is a suffix
  577. /// of the original collection containing the remaining elements.
  578. /// `maxSplits` must be greater than or equal to zero. The default value
  579. /// is `Int.max`.
  580. /// - omittingEmptySubsequences: If `false`, an empty subsequence is
  581. /// returned in the result for each pair of consecutive elements
  582. /// satisfying the `isSeparator` predicate and for each element at the
  583. /// start or end of the collection satisfying the `isSeparator`
  584. /// predicate. The default value is `true`.
  585. /// - whereSeparator: A closure that takes an element as an argument and
  586. /// returns a Boolean value indicating whether the collection should be
  587. /// split at that element.
  588. /// - Returns: A lazy collection of subsequences, split from this collection's
  589. /// elements.
  590. ///
  591. /// - Complexity: O(*n*), where *n* is the length of the collection.
  592. @inlinable
  593. public func split(
  594. maxSplits: Int = Int.max,
  595. omittingEmptySubsequences: Bool = true,
  596. whereSeparator isSeparator: @escaping (Element) -> Bool
  597. ) -> SplitCollection<Elements> {
  598. precondition(maxSplits >= 0, "Must take zero or more splits")
  599. return SplitCollection(
  600. base: elements,
  601. isSeparator: isSeparator,
  602. maxSplits: maxSplits,
  603. omittingEmptySubsequences: omittingEmptySubsequences
  604. )
  605. }
  606. }
  607. extension LazySequenceProtocol
  608. where Self: Collection, Elements: Collection, Element: Equatable
  609. {
  610. /// Lazily returns the longest possible subsequences of the collection, in
  611. /// order, around elements equal to the given element.
  612. ///
  613. /// The resulting lazy collection consists of at most `maxSplits + 1`
  614. /// subsequences. Elements that are used to split the collection are not
  615. /// returned as part of any subsequence (except possibly the last one, in the
  616. /// case where `maxSplits` is less than the number of separators in the
  617. /// collection).
  618. ///
  619. /// The following examples show the effects of the `maxSplits` and
  620. /// `omittingEmptySubsequences` parameters when splitting a string at each
  621. /// space character (" "). The first use of `split` returns each word that
  622. /// was originally separated by one or more spaces.
  623. ///
  624. /// let line = "BLANCHE: I don't want realism. I want magic!"
  625. /// for spaceless in line.lazy.split(separator: " ") {
  626. /// print(spaceless)
  627. /// }
  628. /// // Prints
  629. /// // BLANCHE:
  630. /// // I
  631. /// // don't
  632. /// // want
  633. /// // realism.
  634. /// // I
  635. /// // want
  636. /// // magic!
  637. ///
  638. /// The second example passes `1` for the `maxSplits` parameter, so the
  639. /// original string is split just once, into two new strings.
  640. ///
  641. /// for spaceless in line.lazy.split(separator: " ", maxSplits: 1) {
  642. /// print(spaceless)
  643. /// }
  644. /// // Prints
  645. /// // BLANCHE:
  646. /// // I don't want realism. I want magic!
  647. ///
  648. /// The final example passes `false` for the `omittingEmptySubsequences`
  649. /// parameter, so the returned array contains empty strings where spaces
  650. /// were repeated.
  651. ///
  652. /// for spaceless in line.lazy.split(
  653. /// separator: " ",
  654. /// omittingEmptySubsequences: false
  655. /// ) {
  656. /// print(spaceless)
  657. /// }
  658. /// // Prints
  659. /// // BLANCHE:
  660. /// //
  661. /// //
  662. /// // I
  663. /// // don't
  664. /// // want
  665. /// // realism.
  666. /// // I
  667. /// // want
  668. /// // magic!
  669. ///
  670. /// - Parameters:
  671. /// - separator: The element that should be split upon.
  672. /// - maxSplits: The maximum number of times to split the collection, or
  673. /// one less than the number of subsequences to return. If
  674. /// `maxSplits + 1` subsequences are returned, the last one is a suffix
  675. /// of the original collection containing the remaining elements.
  676. /// `maxSplits` must be greater than or equal to zero. The default value
  677. /// is `Int.max`.
  678. /// - omittingEmptySubsequences: If `false`, an empty subsequence is
  679. /// returned in the result for each consecutive pair of `separator`
  680. /// elements in the collection and for each instance of `separator` at
  681. /// the start or end of the collection. If `true`, only nonempty
  682. /// subsequences are returned. The default value is `true`.
  683. /// - Returns: A lazy collection of subsequences split from this collection's
  684. /// elements.
  685. ///
  686. /// - Complexity: O(*n*), where *n* is the length of the collection.
  687. @inlinable
  688. public func split(
  689. separator: Element,
  690. maxSplits: Int = Int.max,
  691. omittingEmptySubsequences: Bool = true
  692. ) -> SplitCollection<Elements> {
  693. precondition(maxSplits >= 0, "Must take zero or more splits")
  694. return SplitCollection(
  695. base: elements,
  696. isSeparator: { $0 == separator },
  697. maxSplits: maxSplits,
  698. omittingEmptySubsequences: omittingEmptySubsequences
  699. )
  700. }
  701. }