0

I have an array with the following structure:

var array = [
  [
    [3, 5], //a
    [8, 2], //b
    [5, 3], //c
    [8, 1]  //d
  ],
  [
    [3, 9], //a
    [7, 4], //b
    [5, 6], //c
    [8, 8]  //d
  ]
]

I wanna get all possible combinations of the sum of the second numbers of 4 parts (a,b,c,d) using everything data from the array (It's hard to formulate, sorry).

Example: Take the second numbers of a, b, c and d of arrays and sum them (5 + 2 + 3 + 1 = 11). After that we take 'b' second number from second array ([x, 2] -> [x, 4]) and sum again (5 + 4 + 3 + 1 = 13), then don't change 'b', take 'c' second number of second array and sum etc.

If we wanna change 'a' second number, we have to take 'a' second number from the second array - we can't use 'b' second number of second array instead of 'a'. 1st a -> 2nd a, 1st b -> 2nd b, 1st c -> 2nd c, 1st d -> 2nd d.

[3, 5],             [3, 5],
[8, 2], -> [n, 4] = [8, 4],
[5, 3],             [5, 3],
[8, 1]              [8, 1]
    11                  13
___________________________

[3, 5],             [3, 5],
[8, 4],             [7, 4],
[5, 3], -> [n, 6] = [5, 6],
[8, 1]              [8, 1]
    13                  16

So there are 16 possible combinations.

I made code using 4 'for...in' statements and it works fine, but I think there is a better way to solve this task (to use less code or to refactor nested statements) - and I don't know which one.

My solution:

var array = [
  [
    [3, 5], //a
    [8, 2], //b
    [5, 3], //c
    [8, 1]  //d
  ],
  [
    [3, 9], //a
    [7, 4], //b
    [5, 6], //c
    [8, 8]  //d
  ]
]

var sum = 0,
    id = 1;

for (var a in array) {
  for (var b in array) {
    for (var c in array) {
      for (var d in array) {
        sum = array[a][0][1] +
            array[b][1][1] +
            array[c][2][1] +
            array[d][3][1];

        console.log('ID: ' + id++ + " Sum = " + sum);
      }
    }
  }
}

Output:

ID: 1 Sum = 11
ID: 2 Sum = 18
ID: 3 Sum = 14
ID: 4 Sum = 21
ID: 5 Sum = 13
ID: 6 Sum = 20
ID: 7 Sum = 16
ID: 8 Sum = 23
ID: 9 Sum = 15
ID: 10 Sum = 22
ID: 11 Sum = 18
ID: 12 Sum = 25
ID: 13 Sum = 17
ID: 14 Sum = 24
ID: 15 Sum = 20
ID: 16 Sum = 27

I wanna know is there the best way to solve this task? Can I change 4 'for...in' statements to something better? How would you solve this task?

I just wanna change

for (var a in array) {
  for (var b in array) {
    for (var c in array) {
      for (var d in array) {
        /* ... */
      }
    }
  }
}

to something better.

P.S. Also quantity of 'for...in' statements depends on quantity of 'parts' in last array.

a, b, c, d = 4 parts
4 parts = 4 'for...in' statements

2 Answers2

0

You can achieve the same functionality in one line using map

// your array
var array = [
  [
    [3, 5], //a
    [8, 2], //b
    [5, 3], //c
    [8, 1], //d
  ],
  [
    [3, 9], //a
    [7, 4], //b
    [5, 6], //c
    [8, 8], //d
  ],
];

// your variables
var sum = 0, id = 1;

// your function as it is
var fun = (a, b, c, d) => {
  sum = array[a][0][1] + array[b][1][1] + array[c][2][1] + array[d][3][1];
  console.log('ID: ' + id++ + ' Sum = ' + sum);
};

// and in just one line using map function
array.map((_, a) => array.map((_, b) => array.map((_, c) => array.map((_, d) => fun(a, b, c, d)))))
Ahmed Kamal
  • 2,660
  • 3
  • 21
  • 36
0

A nerdy solution: we always know that for 2 arrays with size of n, there will be 2^n combinations. Also, number can be represent in binary format, e.g. 5 as 0101. Each digit in binary format can actually represent which array you should take value from, e.g. 0 will be from array 1, and 1 will be from array 2.

Implementation:

var array = [
  [
    [3, 5], //a
    [8, 2], //b
    [5, 3], //c
    [8, 1], //d
  ],
  [
    [3, 9], //a
    [7, 4], //b
    [5, 6], //c
    [8, 8], //d
  ],
];

var sum = 0;
var length = array[0].length;
var noOfCombination = 2**length;
for (var i=0; i<noOfCombination; i++) {
  var binary = (i >>> 0).toString(2).padStart(length, '0');
  for (var j=0; j<binary.length; j++) {
    if (binary[j] === '0') {
      sum += array[0][j][1];
    } else {
      sum += array[1][j][1]
    }
  }
  console.log('ID: ' + (i + 1) + " Sum = " + sum);
  sum = 0;
}
blaz
  • 3,981
  • 22
  • 37