import type from './type';
import arrays from './array';
/**
* Provides functions for enumerables (object/arrays)
*
* @module Utils
* @class Utils.Enums
* @static
*/
/**
* Allows to iterate over any enumerable with a function taking up to three
* arguments
*
* @method each
* @for Utils.Enums
* @param {string|array|array-like|object} list The enumerable
* @param {function} fn The iteration function
* @param {*} [scope] Optional context to execute the given function in
* @return {undefined} This returns just nothing
*
* @example
* import {each} from './utils/enums';
*
* var colors = {red: '#f00', green: '#0f0'},
* result = '';
*
* each(colors, function (colorValue, colorName, allColors) {
* result += colorName + ' has HEX of ' + colorValue + '<br>';
* });
*
* result;
* // -> 'green has HEX of #0f0<br>red has HEX of #f00<br>'
*/
export const each = function (list, fn, scope) {
if (type.isObject(list)) {
return Object.keys(list).forEach(function (key) {
fn.call(scope || null, list[key], key, list);
});
}
if (type.isSeq(list)) {
return arrays.toArray(list).forEach(fn, scope || null);
}
}
/**
* Allows to map a function over a enumerable
*
* @method map
* @for Utils.Enums
* @param {string|array|array-like|object} list The enumerable
* @param {function} fn The iteration function
* @param {*} [scope] Optional context to execute the given function in
* @return {array} The mapping
*
* @example
* import {map} from './utils/enums';
*
* var result = map([1, 2, 3], function (n) {
* return n * n;
* });
*
* result;
* // -> [1, 4, 9]
*/
export const map = function (list, fn, scope) {
var _mapped = [];
each(list, function (item, id, seq) {
_mapped.push(fn.call(scope || null, item, id, seq));
});
return _mapped;
}
/**
* Allows to filter any enumerable with a function
*
* @method filter
* @for Utils.Enums
* @param {string|array|array-like|object} list The enumerable
* @param {function} fn The iteration function
* @param {*} [scope] Optional context to execute the function in
* @return {array} Filtered enumerable
*
* @example
* import {filter} from './utils/enums';
*
* var result = filter([1, 2, 3], function (n) {
* return n % 2 !== 0;
* });
*
* result;
* // -> [1, 3]
*/
export const filter = function (list, fn, scope) {
var _filtered = [];
each(list, function (item, id, seq) {
if (fn.call(scope || null, item, id, seq)) {
_filtered.push(item);
}
});
return _filtered;
}
/**
* Allows to reduce or fold a enumerable into a single value
*
* @method reduce
* @for Utils.Enums
* @param {string|array|array-like|object} list The enumerable
* @param {function} fn The iteration function
* @param {*} seed Starting value
* @param {*} [scope] Optional context to execute the function in
* @return {*} Depends on seed
*
* @example
* import {reduce} from './utils/enums';
*
* var add = function (a, b) { return a + b; };
*
* var result = reduce(['hallo', ' ', 'welt'], add, '');
*
* result;
* // -> 'hallo welt'
*/
export const reduce = function (list, fn, seed, scope) {
var _base = seed;
each(list, function (item, id, seq) {
_base = fn.call(scope || null, _base, item, id, seq);
});
return _base;
}
/**
* Allows to reduce or fold a enumerable into a single value from right
*
* @method reduceRight
* @for Utils.Enums
* @param {string|array|array-like|object} list The enumerable
* @param {function} fn The iteration function
* @param {*} seed Starting value
* @param {*} [scope] Optional context to execute the function in
* @return {*} Depends on seed
*
* @example
* import {reduceRight} from './utils/enums';
*
* var add = function (a, b) { return a + b; };
*
* var result = reduceRight(['hallo', ' ', 'welt'], div, '');
*
* result;
* // -> 'welt hallo'
*/
export const reduceRight = function (list, fn, seed, scope) {
if (type.isSeq(list)) {
return reduce(arrays.toArray(list).reverse(), fn, seed, scope);
}
return reduce(list, fn, seed, scope);
}
/**
* Evaluates each item in a enumerable against a predicate function until
* the first truthy evaluation is encountered, returns true if at least
* one item evaluates to true
*
* @method some
* @for Utils.Enums
* @param {string|array|array-like|object} list The enumerable
* @param {function} fn The iteration function
* @param {*} [scope] Optional scope to execute the function in
* @return {boolean} True if one item evaluates to true, false otherwise
*
* @example
* import {some} from './utils/enums';
*
* var betweenTwoAndFive = function (n) {
* return n >= 2 && n <= 5;
* };
*
* var result = some([1, 3, 10], betweenTwoAndFive);
*
* result;
* // -> true
*/
export const some = function (list, fn, scope) {
var _i;
if (type.isObject(list)) {
for (_i in list) {
if (list.hasOwnProperty(_i) && !!fn.call(scope || null, list[_i], _i, list)) {
return true;
}
}
return false;
}
if (type.isSeq(list)) {
return arrays.toArray(list).some(fn, scope || null);
}
return false;
}
/**
* Evaluates each item in a enumerable against a predicate function. Returns
* false as soon as the first falsy evaluation is encountered. Does only
* return true if all items evaluate to true
*
* @method every
* @for Utils.Enums
* @param {string|array|array-like|object} list The enumerable
* @param {function} fn The iteration function
* @param {*} [scope] Optional context to execute the function in
* @return {boolean} True if all evaluations are truthy, false otherwise
*
* @example
* import {every} from './utils/enums';
*
* var betweenTwoAndFive = function (n) {
* return n >= 2 && n <= 5;
* };
*
* var result = every([2, 3, 4], betweenTwoAndFive);
*
* result;
* // -> true
*/
export const every = function (list, fn, scope) {
var _i;
if (type.isObject(list)) {
for (_i in list) {
if (list.hasOwnProperty(_i) && !fn.call(scope || null, list[_i], _i, list)) {
return false;
}
}
return true;
}
if (type.isSeq(list)) {
return arrays.toArray(list).every(fn, scope || null);
}
return false;
}
/**
* Returns the index of a given item inside a enumerable from the left
*
* @method indexOf
* @for Utils.Enums
* @param {string|array|array-like|object} list The enumerable
* @param {*} item The item to compare against
* @return {number} Index or key, -1 if not in enumerable
*
* @example
* import {indexOf} from './utils/enums';
*
* var list = [1, 2, 3, 2, 1];
*
* indexOf(list, 2);
* // -> 1
*/
export const indexOf = function (list, item) {
var _i;
if (type.isObject(list)) {
for (_i in list) {
if (list.hasOwnProperty(_i) && list[_i] === item) {
return _i;
}
}
return -1;
}
if (type.isSeq(list)) {
return arrays.toArray(list).indexOf(item);
}
return -1;
}
/**
* Returns the index of a given item inside a enumerable from the right
*
* @method lastIndexOf
* @for Utils.Enums
* @param {string|array|array-like|object} list The enumerable
* @param {*} item The item to compare against
* @return {number} Index or key, -1 if not in enumerable
*
* @example
* import {lastIndexOf} from './utils/enums';
*
* var list = [1, 2, 3, 2, 1];
*
* lastIndexOf(list, 2);
* // -> 3
*/
export const lastIndexOf = function (list, item) {
var _i;
if (type.isObject(list)) {
for (_i in list) {
if (list.hasOwnProperty(_i) && list[_i] === item) {
return _i;
}
}
return -1;
}
if (type.isSeq(list)) {
return arrays.toArray(list).lastIndexOf(item);
}
return -1;
}
/**
* Finds the first item in a enumerable from the left which evaluates truthy
* by applying a predicate to it
*
* @method find
* @for Utils.Enums
* @param {string|array|array-like|object} list The enumerable
* @param {function} fn The predicate function
* @param {*} [scope] Optional context to execute the predicate in
* @return {*} First item from the left if available
*
* @example
* import {find} from './utils/enums';
*
* const startsWith = (x) => (y) => y[0] === x;
*
* find(['a1', 'b1', 'a2', 'b2'], startsWith('b'));
* // -> 'b1'
*/
export const find = function (list, fn, scope) {
return arrays.first(filter(list, fn, scope));
}
/**
* Finds the first item in a enumerable from the right which evaluates truthy
* by applying a predicate to it
*
* @method findLast
* @for Utils.Enums
* @param {string|array|array-like|object} list The enumerable
* @param {function} fn The predicate function
* @param {*} [scope] Optional context to execute the predicate in
* @return {*} First item from the right if available
*
* @example
* import {findLast} from './utils/enums';
*
* const startsWith = (x) => (y) => y[0] === x;
*
* findLast(['a1', 'b1', 'a2', 'b2'], startsWith('b'));
* // -> 'b2'
*/
export const findLast = function (list, fn, scope) {
return arrays.last(filter(list, fn, scope));
}
export default {
each, map, filter, reduce, reduceRight, every,
some, find, findLast, indexOf, lastIndexOf
};