1

the 2D array I'm dealing with might has different length on each row, like:

var a = [1, 2, 3];
var b = ["orange", "poke"];
var c = ["melon", "table", 93, 71, "rock"];
var arrayA = [a, b, c];

And the I want to get all the combinations of values from array like this:

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

Is this possible to achieve these with loops while dealing with 2D array with various length of in the javascript? If not, is there other way to do this?Thx

  • 1
    You are looking for cartesian product [Cartesian product of multiple arrays in JavaScript](https://stackoverflow.com/questions/12303989/cartesian-product-of-multiple-arrays-in-javascript) – Samer Ayoub May 19 '19 at 01:26

2 Answers2

1

If you want to get each combination and do something with each one a nice way to handle this is use a generator. This avoids creating a potentially large list in memory while still being convenient to loop over each combination. For example:

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)
}
Mark
  • 90,562
  • 7
  • 108
  • 148
1

Here's a rather inefficient solution that does not involve a generator (for platforms that do not support generator functions yet)

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));