Last active
November 22, 2022 05:20
-
-
Save vitaly-t/2e2a658b532c89d7350de109229fed03 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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