编辑:我在这里比较了使用 jsperf 的不同方法,Phrogz 的方式显然是最快的,是这里第 3 次的两倍。
如果我理解正确,您是在询问计算每列数字是不同基数的位置。您可以递归地执行此操作。
function options(opArr, fullArray){
var i = 0, j = opArr.length;
if(j < fullArray.length){ // if opArr doesn't have item from each group, add new group
while(i < fullArray[j]){ // count up for this group
newArr = opArr.slice(0); // clone opArr so we don't run into shared reference troubles, not sure if necessary
newArr[j] = i;
i++;
options(newArr, fullArray); // recurse
}
}else{ // opArr is now a unique array of your items
// console.log(opArr);
}
}
options([], [3, 9, 3, 3]);
注意:此(示例)将导致3 * 9 * 3 * 3 = 243
创建数组。这样你最终会吃掉很多内存。
另一种方法是从整数转换为数组,这可以节省内存使用,因为您可以忘记所有先前计算的数组
function countUp(arrayOfBases, callback, self){
var arr = arrayOfBases.reverse(), x = 1, i = arr.length,
me = (self===undefined?this:self),
makeArr = function(arr, x, fn, me){
var a = arr.slice(0), n = [], i = x, j = 0, k = 0;
while(a.length > 0){
k = a[0];
if(k !== 0) j = i % k, i = (i - j) / k;
else j = 0;
n.unshift(j);
a.shift();
}
fn.call(me,n);
};
while (i-->0) if(arr[i] !== 0) x = x * arr[i];
i = 0;
while(i < x){
makeArr(arr, i, callback, me);
i++;
}
}
countUp([3,9,3,3], function(a){console.log(a);});
另一种方法,类似于前面的方法,保留上次生成的数组,因此循环中的计算更少,但代价是 init 更多。
function countUp2(arrayOfBases, callback, self){
var arr = arrayOfBases.reverse(), x = 1, i = arr.length, last = [],
me = (self===undefined?this:self),
addOne = function(arr, n, fn, me){
var j = n.length, i = j - 1;
n[i]++;
while(j = i, i-- > 0 && n[j] >= arr[j]){
if(arr[j] === 0) n[i] += n[j], n[j] = 0;
else n[i]++, n[j] -= arr[j];
}
return fn.call(me,n.slice(0)), n;
};
while (i-->0){
if(arr[i] !== 0) x = x * arr[i];
last[i] = 0;
}
i = 0;
last[last.length-1] = -1;
while(i < x){
last = addOne(arr, last, callback, me);
i++;
}
}
countUp2([3,9,3,3], function(a){console.log(a);});
所有这些方法都会输出
[0,0,0,0]
[0,0,0,1]
...
[0,8,1,2]
[0,8,2,0]
...
[2,8,2,1]
[2,8,2,2]
然后您可以根据自己的选择进行处理。