Created
August 24, 2018 12:59
-
-
Save icyJoseph/5262c2e34ba8c7c64ea58037a33cbe56 to your computer and use it in GitHub Desktop.
Fun with reduce! Everything here is made with reduce!
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
/** | |
* 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