2

trying to iterate over multiple nested arrays to get every single combination of possible values in a new array.

example:

[
  ['a1', 'a2'],
  ['b1', 'b2'],
  ['c1', 'c2']
]

output:

[
   ['a1'],
   ['a2'],
   ['b1'],
   ['b2'],
   ['c1'],
   ['c2'],
   ['a1', 'b1'],
   ['a1', 'b2'],
   ['a1', 'c1'],
   ['a1', 'c2'],
   ['a2', 'b1'],
   ['a2', 'b2'],
   ['a2', 'c1'],
   ['a2', 'c2'],
   ['b1', 'c1'],
   ['b1', 'c2'],
   ['b2', 'c1'],
   ['b2', 'c2']
]

any idea how I can achieve this, perhaps I need to split arrays in the first place ?

user1751287
  • 491
  • 9
  • 26
  • Do you want *every* single combination or only combinations with 1 and 2 elements in them? – VLAZ Nov 15 '18 at 12:17
  • I think you should 1. Post any attempts of code that you've written and then ask about a specific problem that you're having, and 2. Explain in a little more detail as to how your input maps to that output – Khauri Nov 15 '18 at 12:19
  • Just clarifying: so any combinations with 1..N members. – VLAZ Nov 15 '18 at 12:19
  • 1
    You have [this similar question](https://stackoverflow.com/questions/10834393/php-how-to-get-all-possible-combinations-of-1d-array) but i'm not flagging as duplicate because i'm not sure I understand the logic - why does the first 6 elements in the output are valid, but not `['b1', 'a1']` – Alon Eitan Nov 15 '18 at 12:20
  • I need exactly as above, not all combinations as ['a1', 'b1'] and ['b1', 'a1'] – user1751287 Nov 15 '18 at 12:21
  • Can input have nested array? What then - what behaviour do you expect? – magos Nov 15 '18 at 12:23
  • @magos no, the structure will be as simple as above – user1751287 Nov 15 '18 at 12:24
  • I mean you wrote "to iterate over multiple nested arrays", but good to know. How about falsy values (undefined, null, empty strings) potentially occurring in input data? How should the algorithm behave? – magos Nov 15 '18 at 12:26
  • @magos there will be no falsy values – user1751287 Nov 15 '18 at 12:28

3 Answers3

3

You could create recursive function using two nested for loops and one parameter to keep current row iteration count so you can start next for loop from there.

const data = [['a1', 'a2'], ['b1', 'b2'], ['c1', 'c2']]
const res = []

function comb(data, n = 0, prev = []) {
  for (var i = n; i < data.length; i++) {
    for (var j = 0; j < data[i].length; j++) {
      let el = data[i][j]
      let arr = prev.concat(el);
      if (arr.length <= data[i].length) res.push(arr)
      comb(data, i + 1, arr)
    }
  }
}

comb(data)
console.log(JSON.stringify(res))
Nenad Vracar
  • 118,580
  • 15
  • 151
  • 176
3

You could take an recursive approach by handing over the next indices and collect the temporary arrays.

function getCombinations(array, max) {

    function iter(i, j, temp) {
        if (array[i] && j >= array[i].length) {
            j = 0;
            i++;
        }
        if (!array[i] || temp.length === max) return;
        result.push(temp.concat(array[i][j]));
        iter(i + 1, 0, temp.concat(array[i][j]));
        iter(i, j + 1, temp);
    }

    var result = [];
    iter(0, 0, []);
    return result;
}

var array = [['a1', 'a2'], ['b1', 'b2'], ['c1', 'c2']],
    result = getCombinations(array, 2);

console.log(result.map(a => a.join(' ')));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
3

If you need the order too (so single elements first, pairs last), that can be done too, just it is going to be a bit longer than the other solutions:

var org=[['a1', 'a2'],['b1', 'b2'],['c1', 'c2']];

var res=[];

// singles
org.forEach(arr => {
  arr.forEach(elem => {
    res.push([elem]);
  });
});

// pairs
var start=0;
var end=res.length;
org.forEach(arr => {
  start+=arr.length;
  arr.forEach(elem => {
    for(var i=start;i<end;i++)
      res.push([elem,res[i][0]]);
  });
});

console.log(JSON.stringify(res));

//singles part is a nested pair of loops, pushing all the elements, and //pairs traverses the original array again, just it makes use of the already "flattened" result, end simply keeps the number of single elements (as the length of the array will grow) and start always jumps to the beginning of the next sub-array (so 'a1','a2'-like pairs are not generated, as it was required).

tevemadar
  • 12,389
  • 3
  • 21
  • 49