Skip to content

Instantly share code, notes, and snippets.

@icyJoseph
Created August 24, 2018 12:59
Show Gist options
  • Save icyJoseph/5262c2e34ba8c7c64ea58037a33cbe56 to your computer and use it in GitHub Desktop.
Save icyJoseph/5262c2e34ba8c7c64ea58037a33cbe56 to your computer and use it in GitHub Desktop.
Fun with reduce! Everything here is made with reduce!
/**
* Map
* Map a function fn over every element of arr
* */
const map = (arr, fn) =>
arr.reduce((acc, val, index) => acc.concat(fn(val, index)), []);
/**
* Filter
* Remove elements that do not return truthy when evaluated against the function fn
* */
const filter = (arr, fn) =>
arr.reduce((acc, val, index) => (fn(val, index) ? acc.concat(val) : acc), []);
/**
* Get
* given a string path, get that path from an object
* if the key is non existent or the object is falsy, return the fail parameter, by default null
*/
const get = (obj, path, fail = null) => {
if (!obj) return fail;
// path split gets the object keys, unless these are filenames, like in github's gists... in that case you can't use this approach
return path.split('.').reduce((prev, key) => {
const value = prev ? prev[key] : obj[key];
return value || fail;
}, undefined);
};
/**
* GroupBy
* group objects from an array by a common key
*/
const groupBy = (arr, key) => {
return arr.reduce((prev, curr) => {
const currKey = curr[key];
const prevKey = prev[currKey];
return prevKey
? { ...prev, [currKey]: prevKey.concat([curr]) }
: { ...prev, [currKey]: [curr] };
}, {});
};
/**
* GroupByAsArray
* group objects from an array by a common key
* Often groupBy utilities return an object, which could be annoying to work with...
* In this case we return an array, group by key and payload
*/
const groupByAsArray = (arr, key, payload = 'payload') => {
return arr.reduce((prev, curr) => {
const currKey = curr[key];
const index = prev.findIndex(element => element[key] === currKey);
const value = index !== -1
? [{ [key]: currKey, [payload]: [curr, ...prev[index][payload]] }]
: [{ [key]: currKey, [payload]: [curr] }];
return prev.slice(0, index-1).concat(value).concat(prev.slice(index+1))
}, []);
};
/**
* Pipe
* Takes a group of functions and returns a function that takes arguments, applies them to the first function in the
* group, and passes the result to the next, finally returning the result of the last evaluation
*/
const pipe = (...fns) => (...args) =>
fns.reduce((prev, fn, index) => (index === 0 ? fn(...args) : fn(prev)), args);
/**
* Compose
* Reverse pipe, takes functions in different order
* */
const compose = (...fns) => (...args) =>
fns.reduceRight(
(prev, fn, index) => (index === fns.length - 1 ? fn(...args) : fn(prev)),
args
);
// Asynchronously reduce an array
async function reduce(arr, fn, start = []) {
return arr.reduce(async (prev, val) => {
const acc = await prev;
const curr = await fn(acc, val);
return curr;
}, Promise.resolve(start));
}
// Asynchronously map over an array
async function map(arr, fn) {
return arr.reduce(async (prev, val, index) => {
const acc = await prev;
const curr = await fn(val, index);
return acc.concat(curr);
}, Promise.resolve([]));
}
// Asynchronously filter an array
async function filter(arr, fn) {
return arr.reduce(async (prev, value, index) => {
const acc = await prev;
const condition = await fn(value, index);
if (condition) return acc.concat(value);
return acc;
}, Promise.resolve([]));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment