Add a List<E>.windowed extension
Interesting idea. I'd consider defaulting the step to be the same as size, yielding non-overlapping windows.
I'd probably also default allowing partial slices to true, so the default is to cover the entire list.
extension ListWindowsExtension<E> on List<E> {
/// Creates slices of the list with a fixed [size] and increasing start position.
///
/// The [size] must be greater than zero.
///
/// Increments the start position by [step] for after each slice.
/// If [step] is omitted, it defaults to [size], yielding non-overlapping slices.
/// Otherwise the [step] must be greater than zero.
///
/// If [allowPartial] is `true`, the default, windows near the end of the list are
/// allowed to contain fewer than [size] elements. If set to `false`, the iteration
/// ends when there are no further [step] sized windows left.
Iterable<ListSlice<E>> slices(int size, {int? step = null, bool allowPartial = true}) sync* {
RangeError.checkValueInInterval(size, 1, null, "size");
if (step == null) {
step = size;
} else {
RangeError.checkValueInInterval(step, 1, null, "step");
}
for (var i = 0; i < length; i += step) {
var sliceEnd = i + size;
if (sliceEnd > length) {
if (!allowPartial) return;
sliceEnd = length;
}
yield this.slice(i, sliceEnd);
}
}
}
I think var sliceEnd = i step; should be var sliceEnd = i + size? But otherwise it looks like it should work indeed, from a quick glance.
As a side note, I'm on holidays for a couple of weeks without access to a computer, so I won't be able to address any comments here, but feel free to edit the PR it that helps :-)
Good catch, fixed.
Is this worth revisiting?
Is this worth revisiting?
As far as I know, either my or @lrhn 's implementations are ready to go - I'm not sure what would be necessary to push it across the line. With that said, I'm personally not using Dart anymore at the moment so I don't have any need for this - it looks like some people found the idea useful from the reactions though.
@lrhn - worth running with your suggested version?
I think this is a bit too specialized and speculative. I can't find a good use for it. That means that any implementation we add risks being too heavily tuned towards the one use-case that we know of, and might not be reusable anyway the next time someone needs something similar.
Should it be in Iterable instead of List? Or as well?
Should it return an Iterable<Iterable<T>> on iterables?
And when would you want to use it instead of just writing:
for (var i = 0; i < list.length; i += step) {
var slice = list.slice(i, min(i + step, list.length));
...
}
(I'm not a big fan of trying to do all your computations in iterable chains, just because you can. Sometimes it feels more complicated than just doing the loop.)
I'll vote against adding it at this point. Not convinced the problem is ripe for a solution yet.
Closing given the apparent lack of interest.