Search code examples
javascriptalgorithmrecursioncombinationspermutation

How can I create all combinations of this object's keys/values in JavaScript?


I have the following JavaScript object structure:

var options = {
    optionOne: [true, false],
    optionTwo: [true, false],
    optionThree: [
        null,
        {property1: 9, property2: 7},
        {property1: 4, property2: 12},
        {property1: 16, property2: 14}
    ]
};

Please note that the number of key/pairs in this object will differ. So there might actually be optionFour, optionFive, etc., and each option can have any number or type of values for its array.

I need to iterate through this object and create an array containing objects of all possible option combinations:

[
    {optionOne: true,  optionTwo, true,  optionThree: null},
    {optionOne: false, optionTwo, true,  optionThree: null},
    {optionOne: true,  optionTwo, false, optionThree: null},
    {optionOne: false, optionTwo, false, optionThree: null},
    {optionOne: true,  optionTwo, true,  optionThree: {property1: 9, property2: 7}},
    {optionOne: false, optionTwo, true,  optionThree: {property1: 9, property2: 7}},
    {optionOne: true,  optionTwo, false, optionThree: {property1: 9, property2: 7}},
    {optionOne: false, optionTwo, false, optionThree: {property1: 9, property2: 7}},
    {optionOne: true,  optionTwo, true,  optionThree: {property1: 4, property2: 12}},
    {optionOne: false, optionTwo, true,  optionThree: {property1: 4, property2: 12}},
    {optionOne: true,  optionTwo, false, optionThree: {property1: 4, property2: 12}},
    {optionOne: false, optionTwo, false, optionThree: {property1: 4, property2: 12}},
    {optionOne: true,  optionTwo, true,  optionThree: {property1: 16, property2: 14}},
    {optionOne: false, optionTwo, true,  optionThree: {property1: 16, property2: 14}},
    {optionOne: true,  optionTwo, false, optionThree: {property1: 16, property2: 14}},
    {optionOne: false, optionTwo, false, optionThree: {property1: 16, property2: 14}}
]

I'm struggling on how to accomplish this but am fairly confident the answer lies in recursion.

Can the algorithm gods help me?


Solution

  • function getCombinations(options, optionIndex, results, current) {
        var allKeys = Object.keys(options);
        var optionKey = allKeys[optionIndex];
    
        var vals = options[optionKey];
    
        for (var i = 0; i < vals.length; i++) {
            current[optionKey] = vals[i];
    
            if (optionIndex + 1 < allKeys.length) {
                getCombinations(options, optionIndex + 1, results, current);
            } else {
                // The easiest way to clone an object.
                var res = JSON.parse(JSON.stringify(current));
                results.push(res);
            }
        }
    
        return results;
    }
    

    Use it like this:

    var results = getCombinations(options, 0, [], {});
    

    Here's a working JSFiddle example.