UNPKG

vtils

Version:

一个面向业务的 JavaScript/TypeScript 实用程序库。

103 lines (101 loc) 3.44 kB
var supportNewFunction = function () { try { return new Function('return 1')() === 1; } catch (err) { return false; } }(); /** * 计算多个数组的笛卡尔积。 * * @param arr 数组内容 * @example * ```typescript * cartesianProduct([ * ['a', 'b'], * [1, 2], * ]) * // => [['a', 1], ['a', 2], ['b', 1], ['b', 2]] * ``` */ export function cartesianProduct(arr) { if (!Array.isArray(arr)) { throw new Error('cartesianProduct expects an array'); } if (!arr.length) { return []; } if (!Array.isArray(arr[0])) { throw new Error('set at index 0 must be an array'); } return (supportNewFunction && arr.length < 100 ? // 在支持动态构造函数环境下,并且数组长度小于 100 时使用快速模式 cartesianProductProviders.fast : // 否则使用通用模式,如:小程序、数组长度大于等于 100 cartesianProductProviders.universal).run(arr); } var cartesianProductProviders = { // https://github.com/angus-c/just/blob/master/packages/array-cartesian-product/index.js universal: { run: function run(arr) { // initialize our product array var product = arr[0].map(function (v) { return [v]; }); for (var i = 1; i < arr.length; i++) { if (!Array.isArray(arr[i])) { throw new Error("set at index " + i + " must be an array"); } product = cartesianProductProviders.universal.baseProduct(product, arr[i]); } return product; }, baseProduct: function baseProduct(prevProduct, arr2) { // pre allocate all our memory var newProduct = new Array(prevProduct.length * arr2.length); for (var i = 0; i < prevProduct.length; i++) { for (var j = 0; j < arr2.length; j++) { // always provide array to array.concat for consistent behavior newProduct[i * arr2.length + j] = prevProduct[i].concat([arr2[j]]); } } return newProduct; } }, // https://github.com/ehmicky/fast-cartesian/blob/main/src/main.js fast: { cache: Object.create(null), run: function run(arr) { var loopFunc = cartesianProductProviders.fast.getLoopFunc(arr.length); var result = []; loopFunc(arr, result); return result; }, getLoopFunc: function getLoopFunc(length) { var cachedLoopFunc = cartesianProductProviders.fast.cache[length]; if (cachedLoopFunc !== undefined) { return cachedLoopFunc; } var loopFunc = cartesianProductProviders.fast.mGetLoopFunc(length); cartesianProductProviders.fast.cache[length] = loopFunc; return loopFunc; }, mGetLoopFunc: function mGetLoopFunc(length) { var prefixArr = []; var startArr = []; var middleArr = []; var endArr = []; for (var i = 0; i < length; i++) { prefixArr.push("if (!Array.isArray(arrays[" + i + "])) { throw new Error('set at index " + i + " must be an array') }"); startArr.push("for (var i" + i + " = 0; i" + i + " < arrays[" + i + "].length; i" + i + "++) {"); middleArr.push("arrays[" + i + "][i" + i + "]"); endArr.push("}"); } var prefix = prefixArr.join('\n'); var start = startArr.join('\n'); var middle = middleArr.join(','); var end = endArr.join('\n'); return new Function('arrays', 'result', prefix + "\n" + start + "\nresult.push([" + middle + "])\n" + end); } } };