简体   繁体   中英

Refactoring nested for…in statements

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.

PS 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

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

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, eg 5 as 0101. Each digit in binary format can actually represent which array you should take value from, eg 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; } 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM