Skip to content

Instantly share code, notes, and snippets.

@JamieMason
Last active June 14, 2021 05:20
Show Gist options
  • Save JamieMason/4be6028de0608d5854c0 to your computer and use it in GitHub Desktop.
Save JamieMason/4be6028de0608d5854c0 to your computer and use it in GitHub Desktop.
Perform a deeply recursive reduce on a JSON-encodable JavaScript Object hierarchy.
/**
* Perform a deeply recursive reduce on a set of JSON, or a JSON-encodable Object hierarchy.
*
* @param {Array|Object} collection
* @param {Function} fn
* @param {*} memo
* @return {*}
*/
function deepReduce(collection, fn, memo) {
/**
* @inner
* @param {*} value
* @param {String[]} path
* @return {*}
*/
function iterator(value, path) {
var type = Object.prototype.toString.call(value);
memo = fn(memo, value, path);
if (type === '[object Array]') {
for (var i = 0, len = value.length; i < len; i++) {
iterator(value[i], path.concat(i));
}
} else if (type === '[object Object]') {
for (var key in value) {
iterator(value[key], path.concat(key));
}
}
return memo;
}
return iterator(collection, []);
}
/*
* Equivalent version in TypeScript
*/
import { each, isArray, isObject } from 'lodash';
export function deepReduce<In, Out>(
reducer: (accumulator: Out, value: any, path: Array<string | number>) => Out,
collection: In,
accumulator: Out,
): Out {
const iterator = <T>(value: T, paths: Array<string | number>) => {
accumulator = reducer(accumulator, value, paths);
if (isArray(value) || isObject(value)) {
each(value, (innerValue, innerKey) =>
iterator<typeof innerValue>(innerValue, paths.concat(innerKey)),
);
}
};
iterator<In>(collection, []);
return accumulator;
}
@anicarrr
Copy link

Thanks mate. I was looking for something like this, saved my day!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment