JavaScript: generación de combinaciones a partir de n matrices con m elementos [duplicado]
Tengo problemas para encontrar código para generar combinaciones a partir de n números de matrices con m números de elementos, en JavaScript. He visto preguntas similares sobre esto para otros idiomas, pero las respuestas incorporan magia sintáctica o de biblioteca que no estoy seguro de cómo traducir.
Considere estos datos:
[[0,1], [0,1,2,3], [0,1,2]]
3 matrices, con un número diferente de elementos en ellas. Lo que quiero hacer es obtener todas las combinaciones combinando un elemento de cada matriz.
Por ejemplo:
0,0,0 // item 0 from array 0, item 0 from array 1, item 0 from array 2
0,0,1
0,0,2
0,1,0
0,1,1
0,1,2
0,2,0
0,2,1
0,2,2
Etcétera.
Si el número de matrices fuera fijo, sería fácil realizar una implementación codificada. Pero la cantidad de matrices puede variar:
[[0,1], [0,1]]
[[0,1,3,4], [0,1], [0], [0,1]]
Cualquier ayuda sería muy apreciada.
Aquí hay uno bastante simple y breve que utiliza una función auxiliar recursiva:
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;
}
Uso:
cartesian([0,1], [0,1,2,3], [0,1,2]);
Para hacer que la función tome una matriz de matrices, simplemente cambie la firma a function cartesian(args)
en lugar de usar la sintaxis del parámetro resto.
Sugiero una función generadora recursiva simple :
// 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));