Вот еще один способ сделать это. Я обрабатываю индексы всех массивов, как число, чьи цифры имеют разные базы (например, время и даты), используя длину массива в качестве радиуса.
Итак, используя ваш первый набор данных , первая цифра является базой 2, вторая - базой 4, а третья - базой 3. Счетчик запускает 000, затем идет 001, 002, затем 010. Цифры соответствуют индексам в массивах, а так как порядок сохраняется, это не проблема.
У меня есть скрипка с ней, работающая здесь: http://jsfiddle.net/Rykus0/DS9Ea/1/
и вот код:
// Arbitrary base x number class
var BaseX = function(initRadix){
this.radix = initRadix ? initRadix : 1;
this.value = 0;
this.increment = function(){
return( (this.value = (this.value + 1) % this.radix) === 0);
}
}
function combinations(input){
var output = [], // Array containing the resulting combinations
counters = [], // Array of counters corresponding to our input arrays
remainder = false, // Did adding one cause the previous digit to rollover?
temp; // Holds one combination to be pushed into the output array
// Initialize the counters
for( var i = input.length-1; i >= 0; i-- ){
counters.unshift(new BaseX(input[i].length));
}
// Get all possible combinations
// Loop through until the first counter rolls over
while( !remainder ){
temp = []; // Reset the temporary value collection array
remainder = true; // Always increment the last array counter
// Process each of the arrays
for( i = input.length-1; i >= 0; i-- ){
temp.unshift(input[i][counters[i].value]); // Add this array's value to the result
// If the counter to the right rolled over, increment this one.
if( remainder ){
remainder = counters[i].increment();
}
}
output.push(temp); // Collect the results.
}
return output;
}
// Input is an array of arrays
console.log(combinations([[0,1], [0,1,2,3], [0,1,2]]));