/*
In pure JS:
function reduceCompare(arr, cb, cmp, init) {
return (function _(acc, i) {
return i < arr.length && cmp(acc, arr[i], i, arr) === true ? _(cb(acc, arr[i], i, arr), i + 1) : acc;
})(typeof init !== 'undefined' ? init : arr[0], 0);
}
*/
/**
* Reduces an array like Array.prototype.reduce, but with an additional compare function to stop the reduction.
*
* @param arr The array to reduce
* @param cb The callback function for each reduction iteration
* @param cmp The compare function which decides whether to stop or not
* @param init The optional intial value. If omitted, the first array element will be taken.
* @returns The product of the reduction
*/
export default function reduceCompare(
arr: Array
, cb: (
acc: B
, curr: A
, i: number
, arr: Array
) => B
, cmp: (
acc: B
, curr: A
, i: number
, arr: Array
) => boolean
, init?: B
): B {
// testing whether this function was called with the right arguments
if (typeof arr !== 'object' || !Array.isArray(arr)) {
throw new Error('First argument of reduceCompare() must be an array.');
}
if (typeof cb !== 'function') { throw new Error('Second argument of reduceCompare() must be a function.'); }
if (typeof cmp !== 'function') { throw new Error('Third argument of reduceCompare() must be a function.'); }
if (arr.length === 0 && typeof init === 'undefined') { throw new Error(
'Fourth argument of reduceCompare() cannot be undefined if the first argument is an empty array.'
); }
// now comes the magic!
return (function _(acc: B, i: number) {
return i < arr.length && cmp(acc, arr[i], i, arr) === true ? _(cb(acc, arr[i], i, arr), i + 1) : acc;
})(init ?? arr[0] as unknown as B, 0);
}