export function chain (obj) { let chainInstance = { value: function () { return obj; } }; forEach(_, function (method, key) { chainInstance[key] = function () { obj = method(obj, ...arguments); return chainInstance; }; }); return chainInstance; } export function compact (obj) { return filter(obj, val => val ? true : false); } export function contains (obj, value) { if (Array.isArray(obj)) { let length = obj.length; for (let i=0; i {if (predicate(val, key)) result[key] = val;}); } return result; } export function find (obj, predicate) { if (Array.isArray(obj)) { return obj.find(predicate); } else { for (let key in obj) { if (predicate(obj[key])) return obj[key]; } } } export function flatten (list) { if (Array.isArray(list)) { return list.reduce((memo, element) => memo.concat(Array.isArray(element) ? flatten(element) : element), []); } } export function forEach (obj, iteratee) { if (Array.isArray(obj)) { // native 'forEach' but the return below allows us to chain obj.forEach(iteratee); } else { for (let key in obj) { iteratee(obj[key], key, obj); } } return obj; } export function groupBy (obj, iteratee) { let result = {}; forEach(obj, val => { let key = typeof iteratee === 'string' ? val[iteratee] : iteratee(val); result[key] = result[key] || []; result[key].push(val); }); return result; } export function identity (value) { return value; } export function map (obj, iteratee) { let result = []; if (Array.isArray(obj)) { // native 'map' but the return below allows us to chain return obj.map(iteratee); } else { forEach(obj, (value, key) => { result.push(iteratee(value, key, obj)); }); } return result; } function isObject (obj) { return obj && (typeof obj === 'object') && !Array.isArray(obj) ? true : false; } function has (obj, prop) { return obj && obj.hasOwnProperty(prop); } export function mapObj (obj, iteratee) { let result = {}; if (Array.isArray(obj)) { forEach(obj, (value, index) => { let returned = iteratee(value, index, obj); if (isObject(returned) && has(returned, 'key') && has(returned, 'value')) { result[returned.key] = returned.value; } else { result[index] = returned; } }); } else { forEach(obj, (value, key) => { let returned = iteratee(value, key, obj); if (isObject(returned) && has(returned, 'key') && has(returned, 'value')) { result[returned.key] = returned.value; } else { result[key] = returned; } }); } return result; } export function max (obj = [], iteratee) { let max = -Infinity; if (!iteratee) { forEach(obj, value => max = value > max ? value : max); } else { let lastComputed = -Infinity; forEach(obj, (value, index, list) => { let computed = iteratee(value, index, list); if (computed > lastComputed || computed === -Infinity && max === -Infinity) { max = value; lastComputed = computed; } }); } return max; } export function min (obj = [], iteratee) { let min = Infinity; if (!iteratee) { forEach(obj, value => min = value < min ? value : min); } else { let lastComputed = Infinity; forEach(obj, (value, index, list) => { let computed = iteratee(value, index, list); if (computed < lastComputed || computed === Infinity && min === Infinity) { min = value; lastComputed = computed; } }); } return min; } export function omit (obj, keys) { let result = {}; forEach(obj, (value, key) => { if (!contains(keys, key)) { result[key] = value; } }); return result; } export function pick (obj, keys) { let result = {}; keys.forEach(key => { if (obj.hasOwnProperty(key)) { result[key] = obj[key]; } }); return result; } export function range (size, iteratee = identity) { return Array.from(Array(size), (value, index) => iteratee(index)); } export function reduce (obj = [], iteratee, memo = obj[0] != null ? obj[0] : 0) { if (Array.isArray(obj)) { return obj.reduce(iteratee, memo); } else { forEach(obj, (val, key, obj) => { memo = iteratee(memo, val, key, obj); }); } return memo; } export function reject (obj, predicate) { return filter(obj, (val, key, obj) => !predicate(val, key, obj)); } export function some (obj, predicate = identity) { return find(obj, predicate) ? true : false; } export let _ = { compact, contains, filter, find, flatten, forEach, groupBy, identity, map, mapObj, max, min, omit, pick, range, reduce, reject, some };