JavaScript - Generating combinations from n arrays with m elements

I suggest a simple recursive generator function:

// JS
function* cartesianIterator(head, ...tail) {
  const remainder = tail.length ? cartesianIterator(...tail) : [[]];
  for (let r of remainder) for (let h of head) yield [h, ...r];
}

// get values:
const cartesian = items => [...cartesianIterator(items)];
console.log(cartesian(input));
// TS
function* cartesianIterator<T>(items: T[][]): Generator<T[]> {
  const remainder = items.length > 1 ? cartesianIterator(items.slice(1)) : [[]];
  for (let r of remainder) for (let h of items.at(0)!) yield [h, ...r];
}

// get values:
const cartesian = <T>(items: T[][]) => [...cartesianIterator(items)];
console.log(cartesian(input));


You could take an iterative approach by building sub arrays.

var parts = [[0, 1], [0, 1, 2, 3], [0, 1, 2]],
    result = parts.reduce((a, b) => a.reduce((r, v) => r.concat(b.map(w => [].concat(v, w))), []));

console.log(result.map(a => a.join(', ')));
.as-console-wrapper { max-height: 100% !important; top: 0; }

Here is a quite simple and short one using a recursive helper function:

function cartesian(...args) {
    var r = [], max = args.length-1;
    function helper(arr, i) {
        for (var j=0, l=args[i].length; j<l; j++) {
            var a = arr.slice(0); // clone arr
            a.push(args[i][j]);
            if (i==max)
                r.push(a);
            else
                helper(a, i+1);
        }
    }
    helper([], 0);
    return r;
}

Usage:

cartesian([0,1], [0,1,2,3], [0,1,2]);

To make the function take an array of arrays, just change the signature to function cartesian(args) instead of using rest parameter syntax.