UNPKG

cartesian

Version:

Computes the cartesian product of arrays provided by an array or an object

85 lines (72 loc) 1.83 kB
var extend = require('xtend/immutable'); // Public API module.exports = cartesian; /** * Creates cartesian product of the provided properties * * @param {object|array} list - list of (array) properties or array of arrays * @returns {array} all the combinations of the properties */ function cartesian(list) { var last, init, keys, product = []; if (Array.isArray(list)) { init = []; last = list.length - 1; } else if (typeof list == 'object' && list !== null) { init = {}; keys = Object.keys(list); last = keys.length - 1; } else { throw new TypeError('Expecting an Array or an Object, but `' + (list === null ? 'null' : typeof list) + '` provided.'); } function add(row, i) { var j, k, r; k = keys ? keys[i] : i; // either array or not, not expecting objects here Array.isArray(list[k]) || (typeof list[k] == 'undefined' ? list[k] = [] : list[k] = [list[k]]); for (j=0; j < list[k].length; j++) { r = clone(row); store(r, list[k][j], k); if (i >= last) { product.push(r); } else { add(r, i + 1); } } } add(init, 0); return product; } /** * Clones (shallow copy) provided object or array * * @param {object|array} obj - object or array to clone * @returns {object|array} - shallow copy of the provided object or array */ function clone(obj) { return Array.isArray(obj) ? [].concat(obj) : extend(obj); } /** * Stores provided element in the provided object or array * * @param {object|array} obj - object or array to add to * @param {mixed} elem - element to add * @param {string|number} key - object's property key to add to * @returns {void} */ function store(obj, elem, key) { Array.isArray(obj) ? obj.push(elem) : (obj[key] = elem); }