Skip to content

Commit

Permalink
feat(transducers): add IDeref support slidingWindow()
Browse files Browse the repository at this point in the history
(cherry picked from commit c751756)
  • Loading branch information
postspectacular committed May 31, 2020
1 parent 722bf3e commit 13f4184
Showing 1 changed file with 15 additions and 10 deletions.
25 changes: 15 additions & 10 deletions packages/transducers/src/xform/sliding-window.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
import { deref, MaybeDeref } from "@thi.ng/api";
import type { Reducer, Transducer } from "../api";
import { compR } from "../func/compr";
import { $iter } from "../iterator";
import type { Reducer, Transducer } from "../api";

/**
* Sliding window transducer, similar to `partition(size, 1)`, but
* supports initially partially filled windows, if `partial` is set to
* true (default). Each emitted window is a shallow copy of the internal
* accumulation buffer.
*
* @remarks
* If `size` is implements {@link IDeref}, the window size will be
* re-evaluated for each new input and therefore can be used as
* mechanism to dynamically adjust the window size.
*
* @example
* ```ts
* [...window(3, range(5))]
Expand All @@ -22,33 +28,32 @@ import type { Reducer, Transducer } from "../api";
* @param src -
*/
export function slidingWindow<T>(
size: number,
size: MaybeDeref<number>,
partial?: boolean
): Transducer<T, T[]>;
export function slidingWindow<T>(
size: number,
size: MaybeDeref<number>,
src: Iterable<T>
): IterableIterator<T[]>;
export function slidingWindow<T>(
size: number,
size: MaybeDeref<number>,
partial: boolean,
src: Iterable<T>
): IterableIterator<T[]>;
export function slidingWindow<T>(...args: any[]): any {
const iter = $iter(slidingWindow, args);
if (iter) {
return iter;
}
const size: number = args[0];
if (iter) return iter;
const size: MaybeDeref<number> = args[0];
const partial: boolean = args[1] !== false;
return (rfn: Reducer<any, T[]>) => {
const reduce = rfn[2];
let buf: T[] = [];
return compR(rfn, (acc, x: T) => {
buf.push(x);
if (partial || buf.length === size) {
const _size = deref(size);
if (partial || buf.length >= _size) {
acc = reduce(acc, buf);
buf = buf.slice(buf.length === size ? 1 : 0);
buf = buf.slice(buf.length >= _size ? 1 : 0, _size);
}
return acc;
});
Expand Down

0 comments on commit 13f4184

Please sign in to comment.