@mathscapes/iterflow
v1.0.0
Published
Composable streaming statistics pipelines for memory-efficient data processing
Maintainers
Readme
Iterflow
Composable streaming statistics pipelines for JavaScript. Zero dependencies.
import { iter } from '@mathscapes/iterflow';
// Rolling average of stock prices
const prices = [100, 102, 101, 105, 107, 110];
iter(prices)
.window(5)
.map(w => iter(w).mean())
.toArray();
// Process millions of records with constant memory
function* hugeDataset() {
for (let i = 0; i < 1000000; i++) {
yield { valid: i % 2 === 0, value: i };
}
}
iter(hugeDataset())
.filter(x => x.valid)
.map(x => x.value)
.take(1000)
.sum();Install
npm install @mathscapes/iterflowWhy?
ES2025 Iterator Helpers provide lazy transforms (map, filter, take), but lack statistical operations. Libraries like @stdlib/stats/incr provide streaming accumulators, but not as composable pipeline stages. iterflow combines both: lazy pipelines + integrated streaming statistics for memory-efficient multi-stage statistical workflows.
API Reference
Factory Function
iter<T>(src: Iterable<T>): Iterflow<T>Wrap any iterable.
Transform Methods
Transform methods return a new Iterflow<T> and are lazily evaluated. No computation happens until a terminal method is called.
.map<U>(fn: (v: T, i: number) => U): Iterflow<U>Transform each element..filter(fn: (v: T, i: number) => boolean): Iterflow<T>Keep matching elements..flatMap<U>(fn: (v: T, i: number) => Iterable<U>): Iterflow<U>Map and flatten..take(n: number): Iterflow<T>First n elements..drop(n: number): Iterflow<T>Skip first n elements..takeWhile(fn: (v: T, i: number) => boolean): Iterflow<T>Take while predicate is true..dropWhile(fn: (v: T, i: number) => boolean): Iterflow<T>Skip while predicate is true..distinct(): Iterflow<T>Remove duplicates..enumerate(): Iterflow<[number, T]>Yield [index, value] pairs..concat<U>(...others: Iterable<U>[]): Iterflow<T | U>Append iterables..window(size: number): Iterflow<T[]>Sliding windows..chunk(size: number): Iterflow<T[]>Fixed-size chunks..zip<U>(other: Iterable<U>): Iterflow<[T, U]>Combine with another iterable into tuples..zip<U, V>(other1: Iterable<U>, other2: Iterable<V>): Iterflow<[T, U, V]>Combine with two iterables.
Streaming Transform Methods
Streaming methods are transforms that yield intermediate statistical values at each step. Work only on Iterflow<number>.
.streamingMean(): Iterflow<number>Yield running mean at each step..streamingVariance(): Iterflow<number>Yield running variance at each step (Welford's algorithm)..ewma(alpha: number): Iterflow<number>Yield exponentially weighted moving average with decay factor α ∈ (0,1]..streamingZScore(): Iterflow<number>Yield z-scores using running mean/variance from prior observations. NaN for first two elements..streamingCovariance(): Iterflow<number>Yield running covariance for paired streams (requiresIterable<[number, number]>)..streamingCorrelation(): Iterflow<number>Yield running Pearson correlation coefficient for paired streams..windowedMin(size: number): Iterflow<number>Sliding window minimum via monotonic deque. O(1) amortized..windowedMax(size: number): Iterflow<number>Sliding window maximum via monotonic deque. O(1) amortized.
Terminal Methods
Terminal methods consume the iterator and return concrete values.
.toArray(): T[]Collect to array..reduce<U>(fn: (acc: U, v: T, i: number) => U, init: U): UFold to single value..find(fn: (v: T, i: number) => boolean): T | undefinedFirst matching element..forEach(fn: (v: T, i: number) => void): voidExecute function for each..first(): T | undefinedFirst element..last(): T | undefinedLast element..count(): numberCount elements..some(fn: (v: T, i: number) => boolean): booleanAny match?.every(fn: (v: T, i: number) => boolean): booleanAll match?
Statistical Methods
Statistical methods only work on Iterflow<number> and throw EmptySequenceError on empty sequences.
.sum(): numberSum..mean(): numberArithmetic mean..median(): numberMedian (50th percentile)..min(): numberMinimum..max(): numberMaximum..variance(): numberPopulation variance..stdDev(): numberStandard deviation (square root of variance).
Standalone Functions
import { sum, mean, median, min, max, variance, stdDev } from '@mathscapes/iterflow';sum(src: Iterable<number>): numbermean(src: Iterable<number>): numbermedian(src: Iterable<number>): numbermin(src: Iterable<number>): numbermax(src: Iterable<number>): numbervariance(src: Iterable<number>): numberstdDev(src: Iterable<number>): number
Error Classes
IterflowErrorBase error class.EmptySequenceErrorThrown by statistical methods on empty sequences. Hasop: stringproperty.
Type Exports
import type { Predicate, Mapper, Reducer, FlatMapper } from '@mathscapes/iterflow';Predicate<T>=(v: T, i: number) => booleanMapper<T, U>=(v: T, i: number) => UReducer<T, U>=(acc: U, v: T, i: number) => UFlatMapper<T, U>=(v: T, i: number) => Iterable<U>
Utility Functions
isIterable(v: unknown): v is Iterable<unknown>Type guard for iterables.
Benchmarks
Performance benchmarks comparing iterflow against Lodash, iter-ops, RxJS, and native methods are available in the benchmarks/ directory. See benchmarks/README.md for reproduction instructions.
Examples
See the examples/ directory for examples comparing iterflow with native JavaScript, Lodash, and RxJS.
TypeScript
Full type inference. Statistical methods are constrained to Iterflow<number>:
iter(['a', 'b', 'c']).sum() // TypeScript error
iter([1, 2, 3]).sum() // OK: numberLicense
MIT
