Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(collections/unstable): support Iterable argument in slidingWindows #6095

Merged
merged 11 commits into from
Oct 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions collections/deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
"./unstable-chunk": "./unstable_chunk.ts",
"./unstable-drop-last-while": "./unstable_drop_last_while.ts",
"./unstable-sample": "./unstable_sample.ts",
"./unstable-sliding-windows": "./unstable_sliding_windows.ts",
"./unstable-sort-by": "./unstable_sort_by.ts",
"./unstable-take-while": "./unstable_take_while.ts",
"./unstable-without-all": "./unstable_without_all.ts",
Expand Down
101 changes: 101 additions & 0 deletions collections/unstable_sliding_windows.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
// This module is browser compatible.

/** Options for {@linkcode slidingWindows}. */
export interface SlidingWindowsOptions {
/**
* If step is set, each window will start that many elements after the last
* window's start.
*
* @default {1}
*/
step?: number;
/**
* If partial is set, windows will be generated for the last elements of the
* collection, resulting in some undefined values if size is greater than 1.
*
* @default {false}
*/
partial?: boolean;
}

/**
* Generates sliding views of the given iterable of the given size and returns an
* array containing all of them.
*
* @experimental **UNSTABLE**: New API, yet to be vetted.
*
* If step is set, each window will start that many elements after the last
* window's start. (Default: 1)
*
* If partial is set, windows will be generated for the last elements of the
* collection, resulting in some undefined values if size is greater than 1.
*
* @typeParam T The type of the array elements.
*
* @param iterable The iterable to generate sliding windows from.
* @param size The size of the sliding windows.
* @param options The options for generating sliding windows.
*
* @returns An array containing all sliding windows of the given size.
*
* @example Usage
* ```ts
* import { slidingWindows } from "@std/collections/unstable-sliding-windows";
* import { assertEquals } from "@std/assert";
* const numbers = [1, 2, 3, 4, 5];
*
* const windows = slidingWindows(numbers, 3);
* assertEquals(windows, [
* [1, 2, 3],
* [2, 3, 4],
* [3, 4, 5],
* ]);
*
* const windowsWithStep = slidingWindows(numbers, 3, { step: 2 });
* assertEquals(windowsWithStep, [
* [1, 2, 3],
* [3, 4, 5],
* ]);
*
* const windowsWithPartial = slidingWindows(numbers, 3, { partial: true });
* assertEquals(windowsWithPartial, [
* [1, 2, 3],
* [2, 3, 4],
* [3, 4, 5],
* [4, 5],
* [5],
* ]);
* ```
*/
export function slidingWindows<T>(
iterable: Iterable<T>,
size: number,
options: SlidingWindowsOptions = {},
): T[][] {
const { step = 1, partial = false } = options;
if (!Number.isInteger(size) || size <= 0) {
throw new RangeError(
`Cannot create sliding windows: size must be a positive integer, current value is ${size}`,
);
}
if (!Number.isInteger(step) || step <= 0) {
throw new RangeError(
`Cannot create sliding windows: step must be a positive integer, current value is ${step}`,
);
}
const array = Array.isArray(iterable) ? iterable : Array.from(iterable);
const len = array.length;
const result: T[][] = [];
for (let i = 0; i <= len; i += step) {
let last = i + size;
if (last > len) {
last = len;
}
const window: T[] = array.slice(i, last);
if ((partial && window.length) || window.length === size) {
result.push(window);
}
}
return result;
}
Loading