tbowden
tbowden

Reputation: 1058

JavaScript - Finding all combinations including individual and dual combinations?

I have an array of objects I am trying to find all the combinations for. I have got some code that finds all the combinations, however it only find the number of combinations based on the length of the input array.

For example if I use the below array and with the function below I get 27 potential combinations, however that doesn't include elements on their own or in twos.

[
[{ optionName: "red" },{ optionName: "blue"  },{ optionName: "green" }],
[{ optionName: "S" },{ optionName: "L" },{ optionName: "XL" }],
[{ optionName: "spotted" },{ optionName: "striped" },{ optionName: "lined" }],
]

For example I get combinations that look like this:

[{ optionName: "red" },{ optionName: "L"  },{ optionName: "spotted" }]
[{ optionName: "red" },{ optionName: "S"  },{ optionName: "spotted" }]
[{ optionName: "red" },{ optionName: "S"  },{ optionName: "lined" }]

However I want to also include combinations like:

[{ optionName: "red" }]
[{ optionName: "red" },{ optionName: "S"  }]
[{ optionName: "red" },{ optionName: "L"  }]

This is the code I am working with:

       var r = [],
        arg = arrayCombOptions,
        max = arg.length - 1;
      function helper(arr, i) {
        for (var j = 0, l = arg[i].length; j < l; j++) {
          var a = arr.slice(0);
          a.push(arg[i][j]);
          if (i == max) r.push(a);
          else helper(a, i + 1);
        }
      }
      helper([], 0);

How do I find all the combinations including individual and dual combinations?

Upvotes: 1

Views: 48

Answers (2)

grzim
grzim

Reputation: 604

A clean and simple solution: You need to iterate through the array of arrays and for each individual array find all of the possibilities.

const addToEach = (element, arr) => [...arr, element];

const getAllPossibilitesForSingleArr = (arr) => {
  let r = [];
  for(let i=0;i<arr.length;i++) {
    const combinationsSoFarWithNewElementAdded = r.map(ar => addToEach(arr[i],ar))
    r.push(...combinationsSoFarWithNewElementAdded, [arr[i]]);
  }
 return r;
};


const getAllPossibilitesForArrays = arrays => arrays.map(getAllPossibilitesForSingleArr);

In order to find every possibility in a single array I have iterated through the array and in each iteration, I am expanding the result array with a new element and all combinations so far with the new element added.

You can also do it with pure functions (always better):

const getAllPossibilitesForSingleArrFunc = (arr) =>
  arr.reduce((acc, curr,i) => {
    const combinationsSoFarWithNewElementAdded = acc.map(ar => addToEach(arr[i],ar))
    return [...acc, [arr[i]], ...combinationsSoFarWithNewElementAdded]
  },[]);

const getAllPossibilitesForArraysFunc = arrays => arrays.map(getAllPossibilitesForSingleArrFunc);

Upvotes: 0

Nina Scholz
Nina Scholz

Reputation: 386654

You could add for each inner array a dummy like undefined, generate a cartesian product, map only arrays without undefined and slice the array from one, because the first is empty as well.

var data = [[{ optionName: "red" }, { optionName: "blue" }, { optionName: "green" }], [{ optionName: "S" }, { optionName: "L" }, { optionName: "XL" }], [{ optionName: "spotted" }, { optionName: "striped" }, { optionName: "lined" }]], 
    result = data
        .map(a => [undefined, ...a])
        .reduce((a, b) => a.reduce((r, v) => r.concat(b.map(w => [].concat(v, w))), []))
        .map(a => a.filter(Boolean))
        .slice(1);

console.log(result.length);
document.getElementById('out').innerHTML = JSON.stringify(result, null, 4);
<pre id="out"><pre>

Upvotes: 2

Related Questions