window()
window<
T>(array,size):T[][]
Creates a sliding window array of consecutive elements.
Returns an array of overlapping subarrays of the specified size, each shifted by one element from the previous.
π Why is this a Hidden Gem?
Creates sliding windows over arrays. Instead of writing error-prone for loops with array[i] and array[i+1], get clean tuples like [[1,2,3], [2,3,4], [3,4,5]]. Perfect for moving averages, trend detection, and comparing consecutive elements.
Type Parametersβ
T: Tβ
The type of elements in the array.
Parametersβ
array: readonly T[]β
The source array to process.
size: numberβ
The size of each window (must be a positive integer).
Returns: T[][]β
An array of subarrays, each containing size consecutive elements.
Throwsβ
RangeError When size is not a positive integer.
Sinceβ
2.0.0
Performanceβ
O(nΓm) time & space, pre-allocated array, early return when size > length.
Also known asβ
aperture (Ramda) Β· sliding (Effect) Β· window (es-toolkit) Β· β (Lodash, Remeda, Radashi, Modern Dash, Antfu)
Exampleβ
window([1, 2, 3, 4, 5], 3);
// => [[1, 2, 3], [2, 3, 4], [3, 4, 5]]
How it works?β
Window creates overlapping subarrays by sliding one element at a time.
Unlike chunk which splits without overlap, window preserves continuity between groups.
Window vs Chunkβ
| Operation | Overlap | Output for [1,2,3,4,5] size 3 |
|---|---|---|
window(arr, 3) | Yes | [[1,2,3], [2,3,4], [3,4,5]] |
chunk(arr, 3) | No | [[1,2,3], [4,5]] |
Use Casesβ
Detecting changes between consecutive values πβ
Compare adjacent elements to identify transitions, changes, or deltas in sequences. Perfect for tracking state changes, price movements, or any sequential comparisons.
const temperatures = [18, 19, 22, 21, 25, 24];
const changes = window(temperatures, 2).map(([prev, curr]) => curr - prev);
// => [1, 3, -1, 4, -1]
const biggestJump = Math.max(...changes);
// => 4 (between 21 and 25)
Pairwise operations on sequencesβ
Process elements in pairs for comparisons, validations, or transformations. Essential for route calculations, interval analysis, or sequential validations.
const waypoints = ["Paris", "Lyon", "Marseille", "Nice"];
const legs = window(waypoints, 2);
// => [["Paris", "Lyon"], ["Lyon", "Marseille"], ["Marseille", "Nice"]]
const routes = legs.map(([from, to]) => `${from} β ${to}`);
// => ["Paris β Lyon", "Lyon β Marseille", "Marseille β Nice"]
Moving averages for data smoothingβ
Calculate rolling averages to smooth out fluctuations and reveal underlying trends. Essential for financial analysis, sensor data processing, and performance monitoring.
const stockPrices = [100, 102, 98, 105, 110, 108];
const movingAvg = window(stockPrices, 3).map(
(w) => w.reduce((a, b) => a + b, 0) / w.length
);
// => [100, 101.67, 104.33, 107.67]
Render sparkline charts from time seriesβ
Generate point-to-point segments for a mini chart visualization. Essential for inline trend indicators in dashboards and tables.
const prices = [42, 45, 43, 48, 52, 49, 55];
const segments = window(prices, 2).map(([start, end], i) => ({
x1: i * 10,
y1: 100 - start,
x2: (i + 1) * 10,
y2: 100 - end,
color: end >= start ? "green" : "red",
}));
// Render SVG line segments
segments.forEach((s) => drawLine(svg, s));
Buffer visible rows in a virtual scroll viewportβ
Create overlapping windows of rows for smooth virtual scrolling with pre-rendered buffers. Essential for virtual scroll implementations that need buffer zones above and below the viewport.
const allRows = range(0, 5000).map((i) => ({ id: i, label: `Row ${i}` }));
const ROW_HEIGHT = 40;
const VIEWPORT_SIZE = 20;
const BUFFER = 5;
const WINDOW_SIZE = VIEWPORT_SIZE + BUFFER * 2; // 30 rows per window
// Pre-compute overlapping windows for O(1) scroll lookups
const rowWindows = window(allRows, WINDOW_SIZE);
const getVisibleRows = (scrollIndex: number) => {
const windowIndex = clamp(scrollIndex - BUFFER, 0, rowWindows.length - 1);
return rowWindows[windowIndex];
};
container.addEventListener("scroll", throttle(() => {
const scrollIndex = Math.floor(container.scrollTop / ROW_HEIGHT);
renderRows(getVisibleRows(scrollIndex));
}, 16));
Compute stepper transition pairsβ
Generate step transition pairs for animating between wizard steps. Perfect for stepper components with enter/leave animations between steps.
const steps = ["Account", "Profile", "Address", "Payment", "Confirm"];
const transitions = window(steps, 2).map(([from, to]) => ({
from,
to,
animation: `slide-${from}-to-${to}`,
}));
// => [{ from: "Account", to: "Profile", animation: "slide-Account-to-Profile" }, ...]
const animateStep = (currentIndex: number) => {
const transition = transitions[currentIndex];
if (transition) {
playAnimation(transition.animation);
}
};
Detect anomalies in monitoring dataβ
Compare consecutive metric windows to detect sudden spikes or drops. Critical for alerting systems and infrastructure monitoring.
const cpuReadings = [45, 47, 44, 92, 95, 48, 46];
const anomalies = window(cpuReadings, 2)
.map(([prev, curr], i) => ({ index: i + 1, prev, curr, delta: curr - prev }))
.filter((w) => Math.abs(w.delta) > 30);
// => [{ index: 3, prev: 44, curr: 92, delta: 48 }]
anomalies.forEach((a) => alertOps(`CPU spike: ${a.prev}% -> ${a.curr}%`));