編集:ここでjsperfを使用してさまざまな方法を比較しましたが、Phrogzの方法は、ここの3番目の方法の2倍で明らかに最速です。
私が正しく理解していれば、あなたは数字の各列が異なるベースである場所を数えることについて質問しています。これは再帰的に実行できます。
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);});
前と同様の追加の方法で、前回生成された配列を保持するため、ループでの計算が少なくなりますが、初期化のコストが高くなります。
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]
その後、選択したとおりに処理できます。