heyayush
heyayush

Reputation: 195

Cartesian product of array of objects in javascript

I have the following input

input = [{a:[1,2]}, {b:[3,4]}];

and I want to make a cross product output using this input which looks like

output = [{a:1, b:3},{a:1, b:4},{a:2, b:3},{a:2, b:4}];

input could be dynamic like

input = [{a:[1]}, {b:[2,4]}, {c:[3,5,6]}];

Lodash or any standard library could be used.

Upvotes: 4

Views: 1378

Answers (2)

Nenad Vracar
Nenad Vracar

Reputation: 122047

This is how you can do this using recursive function.

function generate(data) {
  var r = [];
  
  function cartesian(data, n, c) {
    if(n == data.length) {
      return r.push(Object.assign({}, c));
    }
    var arr = data[n][Object.keys(data[n])[0]]
    for(var i = 0; i < arr.length; i++) {
      c[Object.keys(data[n])[0]] = arr[i] 
      cartesian(data, n + 1, c);
    }
  }
  
  cartesian(data, 0, {});
  return r;
}
var input1 = [{a:[1,2]}, {b:[3,4]}];
var input2 = [{a:[1]}, {b:[2,4]}, {c:[3,5,6]}];

console.log(generate(input1))
console.log(generate(input2))

Upvotes: 0

Nina Scholz
Nina Scholz

Reputation: 386560

You could use an iterative and recursive approach.

function cartesian(array) {
    function c(part, index) {
        var k = Object.keys(array[index])[0];
        array[index][k].forEach(function (a) {
            var p = Object.assign({}, part, { [k]: a });
            if (index + 1 === array.length) {
                r.push(p);
                return;
            }
            c(p, index + 1);
        });
    }

    var r = [];
    c({}, 0);
    return r;
}

console.log(cartesian([{ a: [1, 2] }, { b: [3, 4] }]));
console.log(cartesian([{ a: [1] }, { b: [2, 4] }, { c: [3, 5, 6] }]));
.as-console-wrapper { max-height: 100% !important; top: 0; }

Upvotes: 6

Related Questions