Last active
May 10, 2019 22:43
-
-
Save highercomve/acf3349f9f9cc44f6883d91c9f6703bb to your computer and use it in GitHub Desktop.
Small library for functional helpers.
This file contains hidden or 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
| function filterIterable (filter, iterable) { | |
| const result = []; | |
| const entries = getEntries(iterable); | |
| for (const [key, value] of entries) { | |
| if (filter(value, key)) { | |
| result.push(value); | |
| } | |
| } | |
| return result; | |
| } | |
| function mapIterable (mapper, iterable) { | |
| const result = []; | |
| const entries = getEntries(iterable); | |
| for (const [key, value] of entries) { | |
| result.push(mapper(value, key)); | |
| } | |
| return result; | |
| } | |
| function everyIterable (mapper, iterable) { | |
| const entries = getEntries(iterable); | |
| for (const [key, value] of entries) { | |
| if (!mapper(value, key)) { | |
| return false; | |
| } | |
| } | |
| return true; | |
| } | |
| export function autoPartial (func) { | |
| const numberOfArguments = func.length; | |
| return (...args) => { | |
| return args.length < numberOfArguments | |
| ? autoPartial(func.bind(null, ...args)) | |
| : func(...args); | |
| }; | |
| } | |
| export function getEntries ( obj ) { | |
| if (obj.entries) { | |
| return obj.entries(); | |
| } | |
| const ownProps = Object.keys(obj); | |
| let i = ownProps.length; | |
| const resArray = new Array(i); | |
| while (i--) { | |
| resArray[i] = [ownProps[i], obj[ownProps[i]]]; | |
| } | |
| return resArray; | |
| } | |
| export const reduce = autoPartial(function _reduce (fn, seed, iterable) { | |
| const iterator = iterable[Symbol.iterator](); | |
| let iterationResult; | |
| let accumulator = seed; | |
| do { | |
| iterationResult = iterator.next(); | |
| accumulator = iterationResult.done ? accumulator : fn(accumulator, iterationResult.value); | |
| } while (!iterationResult.done); | |
| return accumulator; | |
| }); | |
| export const prop = autoPartial(function _prop (path, obj) { | |
| const defaultReturn = arguments[2]; | |
| return path.split(".").reduce((prev, curr) => { | |
| return !prev || !prev.hasOwnProperty(curr) | |
| ? defaultReturn | |
| : defaultReturn | |
| ? prev[curr] || defaultReturn | |
| : prev[curr]; | |
| }, obj); | |
| }); | |
| export const indexBy = autoPartial(function _indexBy (mapper, list) { | |
| const isArray = Array.isArray(list); | |
| const iterable = isArray ? list : Object.keys(list); | |
| const getElement = isArray ? (val) => val : (key) => list[key]; | |
| return iterable.reduce((acc, elem) => { | |
| const element = getElement(elem); | |
| const index = mapper(element); | |
| acc[index] = element; | |
| return acc; | |
| }, {}); | |
| }); | |
| export const all = autoPartial(function _all (mapper, list) { | |
| if (Array.isArray(list)) { | |
| return list.every(mapper); | |
| } else { | |
| return everyIterable(mapper, list); | |
| } | |
| }); | |
| export const isEmpty = autoPartial(function _isEmpty (x) { | |
| return ( | |
| !x | |
| ? true | |
| : x instanceof Map || x instanceof Set | |
| ? x.size === 0 | |
| : Array.isArray(x) | |
| ? x.length === 0 || all(isEmpty, x) | |
| : typeof x === "string" | |
| ? x === "" | |
| : typeof x === "object" | |
| ? Object.keys(x).length === 0 | |
| : void 0 | |
| ); | |
| }); | |
| export const isNotEmpty = autoPartial(function _isNotEmpty (x) { | |
| return !isEmpty(x); | |
| }); | |
| export const pipe = function _pipe (fn, ...funcs) { | |
| if (!fn) { | |
| throw new Error("You need to pipe at least one function"); | |
| } | |
| return (...args) => { | |
| return funcs.reduce((acc, func) => func(acc), fn(...args)); | |
| }; | |
| }; | |
| export const toLower = (x = "") => { | |
| return x.toLowerCase(); | |
| }; | |
| export const filter = autoPartial(function _filter (mapper, list) { | |
| if (Array.isArray(list)) { | |
| return list.filter(mapper); | |
| } else { | |
| return filterIterable(mapper, list); | |
| } | |
| }); | |
| export const includes = autoPartial(function _includes (mapper, list) { | |
| return typeof mapper === "function" && Array.isArray(list) | |
| ? list.findIndex(mapper) >= 0 | |
| : list.indexOf(mapper) >= 0; | |
| }); | |
| export const propEq = autoPartial(function _propEq (mapper, equalTo, obj) { | |
| return prop(mapper, obj) === equalTo; | |
| }); | |
| export const propNotEq = autoPartial(function _propNotEq (mapper, equalTo, obj) { | |
| return !propEq(mapper, equalTo, obj); | |
| }); | |
| export const defaultTo = autoPartial(function _defaultTo (defaultValue, value) { | |
| return isEmpty(value) ? defaultValue : value; | |
| }); | |
| export const omit = autoPartial(function _omit (omitables, obj) { | |
| return omitables.reduce((acc, val) => { | |
| Object.defineProperty(acc, val, { | |
| value: undefined, | |
| enumerable: false, | |
| }); | |
| return acc; | |
| }, Object.assign({}, obj)); | |
| }); | |
| export const pick = autoPartial(function _pick (pickeables, obj) { | |
| return pickeables.reduce((acc, val) => { | |
| acc[val] = obj[val]; | |
| return acc; | |
| }, {}); | |
| }); | |
| export const map = autoPartial(function _map (mapper, list) { | |
| if (list instanceof Map || list instanceof Set) { | |
| return mapIterable(mapper, list); | |
| } | |
| return list.map(mapper); | |
| }); | |
| export const values = autoPartial(function _values (obj) { | |
| if (obj.values || obj instanceof Map || obj instanceof Set) { | |
| return obj.values(); | |
| } | |
| return Object.keys(obj).map((key) => { | |
| return obj[key]; | |
| }); | |
| }); | |
| export const difference = autoPartial(function _difference (first, second) { | |
| const toFilterOut = new Set(second); | |
| return first.reduce((acc, value) => { | |
| if (toFilterOut.has(value)) { | |
| return acc; | |
| } | |
| acc[acc.length] = value; | |
| return acc; | |
| }, []); | |
| }); | |
| export const composeReduce = (fn, ...funcs) => { | |
| const chainFuncs = (...args) => { | |
| return funcs.reduce((acc, func) => func(args[0], acc, args[2] ), fn(...args)); | |
| }; | |
| return autoPartial(function _compose (seed, interable) { | |
| return interable.reduce((acc, value, index) => | |
| chainFuncs(acc, value, index), | |
| seed, | |
| ); | |
| }); | |
| }; | |
| export const uniq = (pChecker) => (pIterable) => { | |
| const iterable = pIterable ? pIterable : pChecker; | |
| const existanceChecker = pIterable ? pChecker : undefined; | |
| if (!existanceChecker) { | |
| return Array.from(new Set(iterable)); | |
| } | |
| return reduce( | |
| (acc, element, index) => { | |
| if (existanceChecker(acc, element, index)) { | |
| return acc; | |
| } | |
| acc.push(element); | |
| return acc; | |
| }, | |
| [], | |
| iterable, | |
| ); | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment