Как получить все комбинации значений в двумерном массиве с циклами, беря одно значение из всей строки каждый раз?
2D-массив, с которым я имею дело, может иметь разную длину в каждой строке, например:
var a = [1, 2, 3];
var b = ["orange", "poke"];
var c = ["melon", "table", 93, 71, "rock"];
var arrayA = [a, b, c];
И я хочу получить все комбинации значений из массива, как это:
var result = [arrayA[0][0], arrayA[1][0], arrayA[2][0]];
//some operation with result
result = [arrayA[0][0], arrayA[1][0], arrayA[2][1]];
//some operation with result
result = [arrayA[0][0], arrayA[1][0], arrayA[2][2]];
//some operation with result
.
.
.
.
.
.
result = [arrayA[0][2], arrayA[1][1], arrayA[2][4]];
//some operation with result
Можно ли добиться этого с помощью циклов при работе с двумерным массивом различной длины в JavaScript? Если нет, есть ли другой способ сделать это?Thx
2 ответа
Решение
Если вы хотите получить каждую комбинацию и сделать что-то с каждой из них, хороший способ справиться с этим - использовать генератор. Это позволяет избежать создания потенциально большого списка в памяти, при этом оставаясь удобным для циклического перебора каждой комбинации. Например:
var a = [1, 2, 3];
var b = ["orange", "poke"];
var c = ["melon", "table", 93, 71, "rock"];
var arrayA = [a, b, c];
function* productGen(arr, cur = []){
if (arr.length < 1) yield cur
else {
for (let item of arr[0]) {
yield* productGen(arr.slice(1), [...cur, item])
}
}
}
for (let combo of productGen(arrayA)){
// do something with combo
console.log(combo)
}
Вот довольно неэффективное решение, которое не включает генератор (для платформ, которые еще не поддерживают функции генератора)
const combinations = arrayA.reduce((previous, current) => {
if (current.length === 0)
return previous;
const accumulate = current.map(x => {
if (previous.length === 0)
return current;
return previous.map(y => {
return [x, y];
});
});
// Flatten combinations
return accumulate.reduce((acc, x) => [...acc, ...x]);
});
combinations.forEach(combination => console.log(combination));