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 ?

9
  • Do you want every single combination or only combinations with 1 and 2 elements in them? Commented Nov 15, 2018 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 Commented Nov 15, 2018 at 12:19
  • Just clarifying: so any combinations with 1..N members. Commented Nov 15, 2018 at 12:19
  • 1
    You have this similar question 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'] Commented Nov 15, 2018 at 12:20
  • I need exactly as above, not all combinations as ['a1', 'b1'] and ['b1', 'a1'] Commented Nov 15, 2018 at 12:21

3 Answers 3

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

Sign up to request clarification or add additional context in comments.

Comments

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

3 Comments

nice idea with nested loops.
@Nina Scholz Thank you, not sure if it works correctly in other scenarios with different array lengths.
i took a limit for max and exit the recursion.
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).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.