window method
Split this iterable using a sliding window.
The window's size is controlled by size
while by
controls the amount by which to increase the window's starting
index. partial
controls whether partial windows smaller than size
at the end are emitted.
Contract
Throws a RangeError if size <= 0
or by <= 0
.
Example
// Overlapping windows
[1, 2, 3, 4, 5].split.window(size: 3, by: 2); // [[1, 2, 3], [3, 4, 5]]
// Non-overlapping windows
[1, 2, 3, 4, 5].split.window(size: 2, by: 3); // [[1, 2], [4, 5]]
// No partial windows
[1, 2, 3, 4].split.window(size: 3, by: 2); // [[1, 2, 3]]
// Partial windows
[1, 2, 3, 4].split.window(size: 3, by: 2, partial: true); // [[1, 2, 3], [3, 4]]
Implementation
@Possible({RangeError})
@lazy @useResult Iterable<List<E>> window({required int size, int by = 1, bool partial = false}) sync* {
RangeError.checkValidRange(1, null, size);
RangeError.checkValidRange(1, null, by);
final iterator = _iterable.iterator;
final window = <E>[];
final overlap = max(0, size - by);
final skip = max(0, by - size);
final unused = size - overlap;
while (true) {
for (var i = window.length; i < size; i++) {
if (!iterator.moveNext()) {
if (partial && overlap < window.length) {
yield [...window];
}
return;
}
window.add(iterator.current);
}
yield [...window];
window.removeRange(0, unused);
for (var i = 0; i < skip; i++) {
if (!iterator.moveNext()) {
return;
}
}
}
}