|
| 1 | +# LazySplit |
| 2 | + |
| 3 | +[[Source](https://github.com/apple/swift-algorithms/blob/main/Sources/Algorithms/LazySplit.swift) | |
| 4 | + [Tests](https://github.com/apple/swift-algorithms/blob/main/Tests/SwiftAlgorithmsTests/LazySplitTests.swift)] |
| 5 | + |
| 6 | +Lazily-evaluating versions of |
| 7 | +[`split(maxSplits:omittingEmptySubsequences:whereSeparator:)`](https://developer.apple.com/documentation/swift/sequence/3128814-split) |
| 8 | +and [`split(separator:maxSplits:omittingEmptySubsequences:)`](https://developer.apple.com/documentation/swift/sequence/3128818-split), |
| 9 | +performing the same operation as their counterparts defined on |
| 10 | +`Sequence` and `Collection`, are added to `LazySequence` and |
| 11 | +`LazyCollection`. The `LazyCollection` methods allow splitting a |
| 12 | +collection without allocating additional storage on the heap. |
| 13 | + |
| 14 | +```swift |
| 15 | +// Splitting a lazy sequence. |
| 16 | +let numbers = stride(from: 1, through: 16, by: 1) |
| 17 | +for subsequence in numbers.lazy.split( |
| 18 | + whereSeparator: { $0 % 3 == 0 || $0 % 5 == 0 } |
| 19 | +) { |
| 20 | + print(subsequence) |
| 21 | +} |
| 22 | +/* Prints: |
| 23 | +[1, 2] |
| 24 | +[4] |
| 25 | +[7, 8] |
| 26 | +[11] |
| 27 | +[13, 14] |
| 28 | +[16] |
| 29 | +*/ |
| 30 | + |
| 31 | +// Splitting a lazy collection. |
| 32 | +let line = "BLANCHE: I don't want realism. I want magic!" |
| 33 | +for subsequence in line.lazy.split(separator: " ") { |
| 34 | + print(subsequence) |
| 35 | +} |
| 36 | +/* Prints |
| 37 | +BLANCHE: |
| 38 | +I |
| 39 | +don't |
| 40 | +want |
| 41 | +realism. |
| 42 | +I |
| 43 | +want |
| 44 | +magic! |
| 45 | +*/ |
| 46 | +``` |
| 47 | + |
| 48 | +## Detailed Design |
| 49 | + |
| 50 | +`LazySequence` and `LazyCollection` are each extended with |
| 51 | +`split(maxSplits:omittingEmptySubsequences:whereSeparator:)` and |
| 52 | +`split(separator:maxSplits:omittingEmptySubsequences:)`. |
| 53 | + |
| 54 | +The `LazySequence` versions of those methods return an instance of |
| 55 | +`LazySplitSequence`. The `LazyCollection` versions return an instance of |
| 56 | +`LazySplitCollection`. |
| 57 | + |
| 58 | +`LazySplitSequence` wraps the sequence to be split, and provides an |
| 59 | +iterator whose `next` method returns a newly-allocated array containing |
| 60 | +the elements of each subsequence in the split sequence in turn. |
| 61 | + |
| 62 | +`LazySplitCollection` wraps the collection to be split. Its `Index` |
| 63 | +wraps a range of base collection indices. `startIndex` is computed at |
| 64 | +initialization. Subscripting a `LazySplitCollection` instance returns |
| 65 | +the slice of the original collection which is the subsequence of the |
| 66 | +split collection at the given index's position. |
| 67 | + |
| 68 | +### Complexity |
| 69 | + |
| 70 | +Iterating a `LazySplitSequence` instance is O(_n_) in time and space, |
| 71 | +since each subsequence returned is a newly-allocated array. |
| 72 | + |
| 73 | +Iterating a `LazySplitCollection` instance is O(_n_) in time and O(1) in |
| 74 | +space, since each subsequence returned is a slice of the base |
| 75 | +collection. Since `startIndex` is computed at initialization, some or |
| 76 | +all of the time cost may be paid at initialization. For example, if the |
| 77 | +base collection contains no elements determined to be separators, it |
| 78 | +will be iterated entirely on initialization of the split collection, and |
| 79 | +all subsequent operations on the split collection, such as |
| 80 | +`index(after:)`, will have complexity O(1). |
0 commit comments