3
3
[[ Source] ( https://github.com/apple/swift-algorithms/blob/main/Sources/Algorithms/Chunked.swift ) |
4
4
[ Tests] ( https://github.com/apple/swift-algorithms/blob/main/Tests/SwiftAlgorithmsTests/ChunkedTests.swift )]
5
5
6
- Break a collection into subsequences where consecutive elements pass a binary
7
- predicate, or where all elements in each chunk project to the same value.
6
+ Break a collection into nonoverlapping subsequences:
8
7
9
- Also, includes a ` chunks(ofCount:) ` that breaks a collection into subsequences
10
- of a given ` count ` .
8
+ * ` chunked(by:) ` forms chunks of consecutive elements that pass a binary predicate,
9
+ * ` chunked(on:) ` forms chunks of consecutive elements that project to equal values,
10
+ * ` chunks(ofCount:) ` forms chunks of a given size, and
11
+ * ` evenlyChunked(into:) ` forms a given number of equally-sized chunks.
11
12
12
- There are two variations of the ` chunked ` method: ` chunked(by:) ` and
13
- ` chunked(on:) ` . ` chunked(by:) ` uses a binary predicate to test consecutive
14
- elements, separating chunks where the predicate returns ` false ` . For example,
15
- you can chunk a collection into ascending sequences using this method:
13
+ ` chunked(by:) ` uses a binary predicate to test consecutive elements, separating
14
+ chunks where the predicate returns ` false ` . For example, you can chunk a
15
+ collection into ascending sequences using this method:
16
16
17
17
``` swift
18
18
let numbers = [10 , 20 , 30 , 10 , 40 , 40 , 10 , 20 ]
19
19
let chunks = numbers.chunked (by : { $0 <= $1 })
20
20
// [[10, 20, 30], [10, 40, 40], [10, 20]]
21
21
```
22
22
23
- The ` chunk (on:)` method, by contrast, takes a projection of each element and
23
+ The ` chunked (on:)` method, by contrast, takes a projection of each element and
24
24
separates chunks where the projection of two consecutive elements is not equal.
25
25
26
26
``` swift
@@ -29,11 +29,10 @@ let chunks = names.chunked(on: \.first!)
29
29
// [["David"], ["Kyle", "Karoy"], ["Nate"]]
30
30
```
31
31
32
- The ` chunks(ofCount:) ` takes a ` count ` parameter (required to be > 0) and separates
33
- the collection into ` n ` chunks of this given count. If the ` count ` parameter is
34
- evenly divided by the count of the base ` Collection ` all the chunks will have
35
- the count equals to the parameter. Otherwise, the last chunk will contain the
36
- remaining elements.
32
+ The ` chunks(ofCount:) ` method takes a ` count ` parameter (required to be > 0) and
33
+ separates the collection into chunks of this given count. If the length of the
34
+ collection is a multiple of the ` count ` parameter, all chunks will have the
35
+ specified size. Otherwise, the last chunk will contain the remaining elements.
37
36
38
37
``` swift
39
38
let names = [" David" , " Kyle" , " Karoy" , " Nate" ]
@@ -44,7 +43,22 @@ let remaining = names.chunks(ofCount: 3)
44
43
// equivalent to [["David", "Kyle", "Karoy"], ["Nate"]]
45
44
```
46
45
47
- The ` chunks(ofCount:) ` is the method of the [ existing SE proposal] [ proposal ] .
46
+ The ` chunks(ofCount:) ` method was previously [ proposed] ( proposal ) for inclusion
47
+ in the standard library.
48
+
49
+ The ` evenlyChunked(into:) ` method takes a ` count ` parameter and divides the
50
+ collection into ` count ` number of equally-sized chunks. If the length of the
51
+ collection is not a multiple of the ` count ` parameter, the chunks at the start
52
+ will be longer than the chunks at the end.
53
+
54
+ ``` swift
55
+ let evenChunks = (0 ..< 15 ).evenlyChunked (into : 3 )
56
+ // equivalent to [0..<5, 5..<10, 10..<15]
57
+
58
+ let nearlyEvenChunks = (0 ..< 15 ).evenlyChunked (into : 4 )
59
+ // equivalent to [0..<4, 4..<8, 8..<12, 12..<15]
60
+ ```
61
+
48
62
Unlike the ` split ` family of methods, the entire collection is included in the
49
63
chunked result — joining the resulting chunks recreates the original collection.
50
64
@@ -53,14 +67,13 @@ c.elementsEqual(c.chunked(...).joined())
53
67
// true
54
68
```
55
69
56
- Check the [ proposal] [ proposal ] detailed design section for more info.
57
-
58
70
[ proposal ] : https://github.com/apple/swift-evolution/pull/935
59
71
60
72
## Detailed Design
61
73
62
- The two methods are added as extension to ` Collection ` , with two matching
63
- versions that return a lazy wrapper added to ` LazyCollectionProtocol ` .
74
+ The four methods are added to ` Collection ` , with matching versions of
75
+ ` chunked(by:) ` and ` chunked(on:) ` that return a lazy wrapper added to
76
+ ` LazyCollectionProtocol ` .
64
77
65
78
``` swift
66
79
extension Collection {
@@ -71,9 +84,14 @@ extension Collection {
71
84
public func chunked <Subject : Equatable >(
72
85
on projection : (Element ) -> Subject
73
86
) -> [SubSequence ]
87
+
88
+ public func chunks (ofCount count : Int ) -> ChunkedByCount<Self >
89
+
90
+ public func evenlyChunked (into count : Int ) -> EvenChunks<Self >
74
91
}
92
+ }
75
93
76
- extension LazyCollectionProtocol {
94
+ extension LazyCollectionProtocol {
77
95
public func chunked (
78
96
by belongInSameGroup : @escaping (Element , Element ) -> Bool
79
97
) -> Chunked<Elements >
@@ -83,9 +101,18 @@ extension Collection {
83
101
) -> Chunked<Elements >
84
102
}
85
103
```
104
+ --------------------------------------------------------------------------------
105
+ The ` Chunked ` type conforms to ` LazyCollectionProtocol ` and also conforms to
106
+ ` BidirectionalCollection ` when the base collection conforms.
107
+
108
+ The ` ChunkedByCount ` type conforms to ` Collection ` and also conforms to both
109
+ ` BidirectionalCollection ` and ` RandomAccessCollection ` when the base collection
110
+ is random-access, as well as to ` LazyCollectionProtocol ` when the base
111
+ collection conforms.
86
112
87
- The ` Chunked ` type is bidirectional when the wrapped collection is
88
- bidirectional.
113
+ The ` EvenChunks ` type conforms to ` Collection ` and also
114
+ conforms to ` BidirectionalCollection ` , ` RandomAccessCollection ` , and
115
+ ` LazyCollectionProtocol ` when the base collection conforms..
89
116
90
117
### Complexity
91
118
@@ -105,5 +132,5 @@ The operation performed by these methods is similar to other ways of breaking a
105
132
** Ruby:** Ruby’s ` Enumerable ` class defines ` chunk_while ` and ` chunk ` , which map
106
133
to the proposed ` chunked(by:) ` and ` chunked(on:) ` methods.
107
134
108
- ** Rust:** Rust defines a variety of size-based ` chunks ` methods, but doesn’t
109
- include any with the functionality described here.
135
+ ** Rust:** Rust defines a variety of size-based ` chunks ` methods, of which the
136
+ standard version corresponds to the ` chunks(ofCount:) ` method defined here.
0 commit comments