Skip to content

Instantly share code, notes, and snippets.

@highercomve
Last active May 10, 2019 22:43
Show Gist options
  • Select an option

  • Save highercomve/acf3349f9f9cc44f6883d91c9f6703bb to your computer and use it in GitHub Desktop.

Select an option

Save highercomve/acf3349f9f9cc44f6883d91c9f6703bb to your computer and use it in GitHub Desktop.
Small library for functional helpers.
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