Как получить все комбинации значений в двумерном массиве с циклами, беря одно значение из всей строки каждый раз?

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));
Другие вопросы по тегам