10
10
//===----------------------------------------------------------------------===//
11
11
12
12
/// A collection wrapper that breaks a collection into chunks based on a
13
- /// predicate or projection.
14
- public struct Chunked < Base: Collection , Subject> {
13
+ /// predicate.
14
+ ///
15
+ /// Call `lazy.chunked(by:)` on a collection to create an instance of this type.
16
+ public struct ChunkedBy < Base: Collection , Subject> {
15
17
/// The collection that this instance provides a view onto.
16
18
@usableFromInline
17
19
internal let base : Base
@@ -45,7 +47,7 @@ public struct Chunked<Base: Collection, Subject> {
45
47
}
46
48
}
47
49
48
- extension Chunked : LazyCollectionProtocol {
50
+ extension ChunkedBy : LazyCollectionProtocol {
49
51
/// A position in a chunked collection.
50
52
public struct Index : Comparable {
51
53
/// The range corresponding to the chunk at this position.
@@ -106,9 +108,9 @@ extension Chunked: LazyCollectionProtocol {
106
108
}
107
109
}
108
110
109
- extension Chunked . Index : Hashable where Base. Index: Hashable { }
111
+ extension ChunkedBy . Index : Hashable where Base. Index: Hashable { }
110
112
111
- extension Chunked : BidirectionalCollection
113
+ extension ChunkedBy : BidirectionalCollection
112
114
where Base: BidirectionalCollection
113
115
{
114
116
/// Returns the index in the base collection of the start of the chunk ending
@@ -131,11 +133,64 @@ extension Chunked: BidirectionalCollection
131
133
}
132
134
}
133
135
134
- @available ( * , deprecated, renamed: " Chunked " )
135
- public typealias LazyChunked < Base: Collection , Subject> = Chunked < Base , Subject >
136
+ @available ( * , deprecated, renamed: " ChunkedBy " )
137
+ public typealias LazyChunked < Base: Collection , Subject> = ChunkedBy < Base , Subject >
138
+
139
+ @available ( * , deprecated, renamed: " ChunkedBy " )
140
+ public typealias Chunked < Base: Collection , Subject> = ChunkedBy < Base , Subject >
141
+
142
+ /// A collection wrapper that breaks a collection into chunks based on a
143
+ /// predicate.
144
+ ///
145
+ /// Call `lazy.chunked(on:)` on a collection to create an instance of this type.
146
+ public struct ChunkedOn < Base: Collection , Subject> {
147
+ @usableFromInline
148
+ internal var chunked : ChunkedBy < Base , Subject >
149
+
150
+ @inlinable
151
+ internal init (
152
+ base: Base ,
153
+ projection: @escaping ( Base . Element ) -> Subject ,
154
+ belongInSameGroup: @escaping ( Subject , Subject ) -> Bool
155
+ ) {
156
+ self . chunked = ChunkedBy ( base: base, projection: projection, belongInSameGroup: belongInSameGroup)
157
+ }
158
+ }
159
+
160
+ extension ChunkedOn : LazyCollectionProtocol {
161
+ public typealias Index = ChunkedBy < Base , Subject > . Index
162
+
163
+ @inlinable
164
+ public var startIndex : Index {
165
+ chunked. startIndex
166
+ }
167
+
168
+ @inlinable
169
+ public var endIndex : Index {
170
+ chunked. endIndex
171
+ }
172
+
173
+ @inlinable
174
+ public subscript( position: Index ) -> ( Subject , Base . SubSequence ) {
175
+ let subsequence = chunked [ position]
176
+ let subject = chunked. projection ( subsequence. first!)
177
+ return ( subject, subsequence)
178
+ }
179
+
180
+ @inlinable
181
+ public func index( after i: Index ) -> Index {
182
+ chunked. index ( after: i)
183
+ }
184
+ }
185
+
186
+ extension ChunkedOn : BidirectionalCollection where Base: BidirectionalCollection {
187
+ public func index( before i: Index ) -> Index {
188
+ chunked. index ( before: i)
189
+ }
190
+ }
136
191
137
192
//===----------------------------------------------------------------------===//
138
- // lazy.chunked(by:)
193
+ // lazy.chunked(by:) / lazy.chunked(on:)
139
194
//===----------------------------------------------------------------------===//
140
195
141
196
extension LazyCollectionProtocol {
@@ -146,8 +201,8 @@ extension LazyCollectionProtocol {
146
201
@inlinable
147
202
public func chunked(
148
203
by belongInSameGroup: @escaping ( Element , Element ) -> Bool
149
- ) -> Chunked < Elements , Element > {
150
- Chunked (
204
+ ) -> ChunkedBy < Elements , Element > {
205
+ ChunkedBy (
151
206
base: elements,
152
207
projection: { $0 } ,
153
208
belongInSameGroup: belongInSameGroup)
@@ -160,41 +215,38 @@ extension LazyCollectionProtocol {
160
215
@inlinable
161
216
public func chunked< Subject: Equatable > (
162
217
on projection: @escaping ( Element ) -> Subject
163
- ) -> Chunked < Elements , Subject > {
164
- Chunked (
218
+ ) -> ChunkedOn < Elements , Subject > {
219
+ ChunkedOn (
165
220
base: elements,
166
221
projection: projection,
167
222
belongInSameGroup: == )
168
223
}
169
224
}
170
225
171
226
//===----------------------------------------------------------------------===//
172
- // chunked(by:)
227
+ // chunked(by:) / chunked(on:)
173
228
//===----------------------------------------------------------------------===//
174
229
175
230
extension Collection {
176
231
/// Returns a collection of subsequences of this collection, chunked by
177
- /// grouping elements that project to the same value according to the given
178
- /// predicate.
232
+ /// the given predicate.
179
233
///
180
234
/// - Complexity: O(*n*), where *n* is the length of this collection.
181
235
@inlinable
182
- internal func chunked< Subject> (
183
- on projection: ( Element ) throws -> Subject ,
184
- by belongInSameGroup: ( Subject , Subject ) throws -> Bool
236
+ public func chunked(
237
+ by belongInSameGroup: ( Element , Element ) throws -> Bool
185
238
) rethrows -> [ SubSequence ] {
186
239
guard !isEmpty else { return [ ] }
187
240
var result : [ SubSequence ] = [ ]
188
241
189
242
var start = startIndex
190
- var subject = try projection ( self [ start] )
243
+ var current = self [ start]
191
244
192
245
for (index, element) in indexed ( ) . dropFirst ( ) {
193
- let nextSubject = try projection ( element)
194
- if try ! belongInSameGroup( subject, nextSubject) {
246
+ if try ! belongInSameGroup( current, element) {
195
247
result. append ( self [ start..< index] )
196
248
start = index
197
- subject = nextSubject
249
+ current = element
198
250
}
199
251
}
200
252
@@ -204,17 +256,6 @@ extension Collection {
204
256
205
257
return result
206
258
}
207
-
208
- /// Returns a collection of subsequences of this collection, chunked by
209
- /// the given predicate.
210
- ///
211
- /// - Complexity: O(*n*), where *n* is the length of this collection.
212
- @inlinable
213
- public func chunked(
214
- by belongInSameGroup: ( Element , Element ) throws -> Bool
215
- ) rethrows -> [ SubSequence ] {
216
- try chunked ( on: { $0 } , by: belongInSameGroup)
217
- }
218
259
219
260
/// Returns a collection of subsequences of this collection, chunked by
220
261
/// grouping elements that project to the same value.
@@ -223,8 +264,27 @@ extension Collection {
223
264
@inlinable
224
265
public func chunked< Subject: Equatable > (
225
266
on projection: ( Element ) throws -> Subject
226
- ) rethrows -> [ SubSequence ] {
227
- try chunked ( on: projection, by: == )
267
+ ) rethrows -> [ ( Subject , SubSequence ) ] {
268
+ guard !isEmpty else { return [ ] }
269
+ var result : [ ( Subject , SubSequence ) ] = [ ]
270
+
271
+ var start = startIndex
272
+ var subject = try projection ( self [ start] )
273
+
274
+ for (index, element) in indexed ( ) . dropFirst ( ) {
275
+ let nextSubject = try projection ( element)
276
+ if subject != nextSubject {
277
+ result. append ( ( subject, self [ start..< index] ) )
278
+ start = index
279
+ subject = nextSubject
280
+ }
281
+ }
282
+
283
+ if start != endIndex {
284
+ result. append ( ( subject, self [ start..< endIndex] ) )
285
+ }
286
+
287
+ return result
228
288
}
229
289
}
230
290
0 commit comments