Skip to content

Instantly share code, notes, and snippets.

@vitaly-t
Last active November 22, 2022 05:20
Show Gist options
  • Save vitaly-t/2e2a658b532c89d7350de109229fed03 to your computer and use it in GitHub Desktop.
Save vitaly-t/2e2a658b532c89d7350de109229fed03 to your computer and use it in GitHub Desktop.
import {aggregate, reduce, skip, take, distinct, map, Operation, tap} from 'iter-ops';
///////////////////////////////////////////////////////////////////////////////
// Collection of custom operators for "iter-ops", made from existing operators,
// as implementation examples + ideas (these are not part of the library).
///////////////////////////////////////////////////////////////////////////////
/**
* Logs values into the console.
*/
export function log<T>(): Operation<T, T> {
return tap((value) => {
console.log(value);
});
}
/**
* Joins strings, with optional separator.
*/
export function join<T>(separator?: string): Operation<T, string> {
return aggregate(a => a.join(separator));
}
/**
* Groups objects by a property value.
*/
export function groupBy<T>(predicate: (v: T) => string): Operation<T, { [key: string]: T[] }> {
return reduce((acc: { [key: string]: T[] }, value: T) => {
(acc[predicate(value)] ||= []).push(value);
return acc;
}, {} as { [key: string]: T[] });
}
/**
* Implements Array->slice logic (for positive start/end only)
*/
export function slice<T>(start: number, end: number): Operation<T, T> {
return i => {
const k = skip<T>(start)(i);
return take<T>(end - start)(k);
};
}
/**
* Emits minimum value.
*/
export function min<T>(): Operation<T, T> {
return reduce((p, c) => p < c ? p : c);
}
/**
* Emits maximum value.
*/
export function max<T>(): Operation<T, T> {
return reduce((p, c) => p > c ? p : c);
}
/**
* Emits {min, max} in one iteration.
*/
export function minMax<T>(): Operation<T, { min?: T, max?: T }> {
return reduce((p, c) => {
p.min = c < p.min ? c : p.min ?? c;
p.max = c > p.max ? c : p.max ?? c;
return p;
}, {min: undefined, max: undefined});
}
/**
* Emits an average value.
*/
export function average<T>(): Operation<T, T> {
return reduce((p, c, idx, state) => {
state.sum = (state.sum ?? p) + c;
return p && state.sum / (idx + 1) as any;
});
}
/**
* Sums up a sequence of numbers.
*/
export function sum(): Operation<number, number> {
return reduce((p: number, c: number) => p + c);
}
/**
* Selects unique key-values, then remaps them into just values.
*/
export function uniqueValues<T, R>(keySelector: (value: T, index: number) => R): Operation<T, R> {
return i => {
const k = distinct(keySelector)(i);
return map(keySelector)(k);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment