0

Note: This question is different than other permutation questions because it's an array of objects and not an array of integers.

I have an array of objects like this:

var options = 
[
    {
        name: "Size",
        choices: [
            {
                label: "Small",
                price: 0
            },
            {
                label: "Medium",
                price: 10
            }
        ]
    },
    {
        name: "Color",
        choices: [
            {
                label: "Yellow",
                price: 0
            },
            {
                label: "Purple",
                price: 10
            }
        ]
    }
]

I want to make a function that generates all possible variations into an object like this:

{
    "Size-Small--Color-Yellow": {
        label: "Size: Small, Color: Yellow",
        choices: {
            Size: {
                label: "Small",
                price: 0
            },
            Color: {
                label: "Yellow",
                price: 0,
            }
        },
    },
    "Size-Small--Color-Purple": {
        label: "Size: Small, Color: Purple",
        choices: {
            Size: {
                label: "Small",
                price: 0
            },
            Color: {
                label: "Purple",
                price: 10,
            }
        },
    },
    "Size-Medium--Color-Yellow": {
        label: "Size: Medium, Color: Yellow",
        choices: {
            Size: {
                label: "Medium",
                price: 10
            },
            Color: {
                label: "Yellow",
                price: 0,
            }
        },
    },
    "Size-Medium--Color-Purple": {
        label: "Size: Medium, Color: Purple",
        choices: {
            Size: {
                label: "Medium",
                price: 10
            },
            Color: {
                label: "Purple",
                price: 10,
            }
        },
    }
}

The real array of objects is much larger which a lot more options and choices, so the solution would need to work with various array sizes, from small like this to very large sets of options.

Here is what I tried so far:

function generateVariations() {
    var variations = {};

    for(var i in options) {
      var option = options[i];
      var key = '';
      var keyArray = [];
      for(var j in option.choices) {
        var choice = option.choices[j];
        console.log(choice, 'choice value');

        keyArray.push(option.name + '-' + choice.label)
      }

      key = keyArray.join('--');

      console.log(key, 'key made for object');

      variations[key] = {}; // TODO: After generating all of the keys, assign them correct values.
    }

    return variations;
}

I'm having trouble wrapping my head around the recursive aspect of this, since there could potentially be unlimited numbers of variations, not sure if it needs recursion or not.

Jordash
  • 2,926
  • 8
  • 38
  • 77
  • why is the price of medium + purple 10? – Jonas Wilms Jan 02 '19 at 23:14
  • @JonasWilms Sorry was a typo, that's fixed – Jordash Jan 02 '19 at 23:17
  • 1
    *This question is different than other permutation questions because it's an array of objects and not an array of integers.* — think of each option as a place value in a number, with as many possible values as there are choices. Thus if there are 10 option types with 3 choices each, your job is just enumerating all 59,049 values. – Pointy Jan 02 '19 at 23:18

1 Answers1

2

Using recursion is probably the most elegant way here, and I would use a generator function as you can generate the values step by step, which will also work if there is an infinite number of combimations:

 function* combine(options, index = 0, previous = {}) {
   if(index >= options.length) yield previous;
   const { name, choices } = options[index];

   for(const { label, price } of choices) {
     yield* combine(options, index + 1, { ...previous, [name]: { label, price }});
   }
}

Usable as:

 for(const combo of combinations(options))
   console.log(combo);
Jonas Wilms
  • 132,000
  • 20
  • 149
  • 151