Skip to content

Commit 45be5d3

Browse files
authored
feat(collections/unstable): support Iterable argument in slidingWindows (#6095)
1 parent 825f311 commit 45be5d3

File tree

3 files changed

+437
-0
lines changed

3 files changed

+437
-0
lines changed

collections/deno.json

+1
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@
5151
"./unstable-drop-last-while": "./unstable_drop_last_while.ts",
5252
"./unstable-intersect": "./unstable_intersect.ts",
5353
"./unstable-sample": "./unstable_sample.ts",
54+
"./unstable-sliding-windows": "./unstable_sliding_windows.ts",
5455
"./unstable-sort-by": "./unstable_sort_by.ts",
5556
"./unstable-take-last-while": "./unstable_take_last_while.ts",
5657
"./unstable-take-while": "./unstable_take_while.ts",
+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
2+
// This module is browser compatible.
3+
4+
/** Options for {@linkcode slidingWindows}. */
5+
export interface SlidingWindowsOptions {
6+
/**
7+
* If step is set, each window will start that many elements after the last
8+
* window's start.
9+
*
10+
* @default {1}
11+
*/
12+
step?: number;
13+
/**
14+
* If partial is set, windows will be generated for the last elements of the
15+
* collection, resulting in some undefined values if size is greater than 1.
16+
*
17+
* @default {false}
18+
*/
19+
partial?: boolean;
20+
}
21+
22+
/**
23+
* Generates sliding views of the given iterable of the given size and returns an
24+
* array containing all of them.
25+
*
26+
* @experimental **UNSTABLE**: New API, yet to be vetted.
27+
*
28+
* If step is set, each window will start that many elements after the last
29+
* window's start. (Default: 1)
30+
*
31+
* If partial is set, windows will be generated for the last elements of the
32+
* collection, resulting in some undefined values if size is greater than 1.
33+
*
34+
* @typeParam T The type of the array elements.
35+
*
36+
* @param iterable The iterable to generate sliding windows from.
37+
* @param size The size of the sliding windows.
38+
* @param options The options for generating sliding windows.
39+
*
40+
* @returns An array containing all sliding windows of the given size.
41+
*
42+
* @example Usage
43+
* ```ts
44+
* import { slidingWindows } from "@std/collections/unstable-sliding-windows";
45+
* import { assertEquals } from "@std/assert";
46+
* const numbers = [1, 2, 3, 4, 5];
47+
*
48+
* const windows = slidingWindows(numbers, 3);
49+
* assertEquals(windows, [
50+
* [1, 2, 3],
51+
* [2, 3, 4],
52+
* [3, 4, 5],
53+
* ]);
54+
*
55+
* const windowsWithStep = slidingWindows(numbers, 3, { step: 2 });
56+
* assertEquals(windowsWithStep, [
57+
* [1, 2, 3],
58+
* [3, 4, 5],
59+
* ]);
60+
*
61+
* const windowsWithPartial = slidingWindows(numbers, 3, { partial: true });
62+
* assertEquals(windowsWithPartial, [
63+
* [1, 2, 3],
64+
* [2, 3, 4],
65+
* [3, 4, 5],
66+
* [4, 5],
67+
* [5],
68+
* ]);
69+
* ```
70+
*/
71+
export function slidingWindows<T>(
72+
iterable: Iterable<T>,
73+
size: number,
74+
options: SlidingWindowsOptions = {},
75+
): T[][] {
76+
const { step = 1, partial = false } = options;
77+
if (!Number.isInteger(size) || size <= 0) {
78+
throw new RangeError(
79+
`Cannot create sliding windows: size must be a positive integer, current value is ${size}`,
80+
);
81+
}
82+
if (!Number.isInteger(step) || step <= 0) {
83+
throw new RangeError(
84+
`Cannot create sliding windows: step must be a positive integer, current value is ${step}`,
85+
);
86+
}
87+
const array = Array.isArray(iterable) ? iterable : Array.from(iterable);
88+
const len = array.length;
89+
const result: T[][] = [];
90+
for (let i = 0; i <= len; i += step) {
91+
let last = i + size;
92+
if (last > len) {
93+
last = len;
94+
}
95+
const window: T[] = array.slice(i, last);
96+
if ((partial && window.length) || window.length === size) {
97+
result.push(window);
98+
}
99+
}
100+
return result;
101+
}

0 commit comments

Comments
 (0)