Evenly divide a collection into chunks
Divide a collection into a given number of chunks as evenly as possible, with larger chunks at the start.
for chunk in Array(0..<10).evenlyChunked(in: 4) {
print(chunk) // [0, 1, 2], [3, 4, 5], [6, 7], [8, 9]
}
EvenChunks<Base>.SubSequence is set to be EvenChunks<Base.SubSequence> which works out rather nicely. Other collections in this package that could benefit from this as well are LazyChunked, ChunkedByCount, and Windows.
Checklist
- [x] I've added at least one test that validates that my change is working, if appropriate
- [x] I've followed the code style of the rest of the project
- [x] I've read the Contribution Guidelines
- [x] I've updated the documentation if necessary
@swift-ci please test
I tried for a bit to make EvenChunks<Base>.SubSequence equal to EvenChunks<Base.SubSequence>, but it doesn't really seem to be possible (with how EvenChunks.Index currently works)!
It is important that Index only uses its offset property when testing for equality, because two unequal indices can correspond to the same empty slice of the base collection when the number of chunks exceeds the size of the collection:
print(Array((0..<3).evenlyChunked(into: 5)))
// [0..<1, 1..<2, 2..<3, 3..<3, 3..<3]
At the same time, every collection subsequence needs to share its indices with the collection it came from, in particular:
let chunks = (0..<6).evenlyChunked(into: 2)
let index = chunks.index(after: chunks.startIndex)
let slice = chunks[index...]
print(index == slice.startIndex) // should print "true"
This is problematic because the slice doesn't know it's a slice, and so it assigns its startIndex an offset of 0, not 1. EvenChunks would need an extra stored property to make this work which is a line I didn't want to cross.
@swift-ci please test
I think I like evenlyChunked(in: 4) more than evenlyChunked(into: 4), since into has connotations of the argument being passed inout, for example:
-
hash(into:) -
reduce(into:_:)
@swift-ci please test
@swift-ci Please test