I have an array of objects and want to create all possible unique combinations based on two keys.
Example input -
[
{ slot: 'body', spell: 'combat.i', item: 'body combat1'},
{ slot: 'body', spell: 'combat.i', item: 'body combat2'},
{ slot: 'body', spell: 'strength.i', item: 'body str1' },
{ slot: 'body', spell: 'dexterity.i', item: 'body dex1' },
{ slot: 'legs', spell: 'dexterity.i', item: 'legs dex1' },
{ slot: 'legs', spell: 'combat.i', item: 'legs combat1' },
{ slot: 'legs', spell: 'strength.i', item: 'legs str1' },
{ slot: 'head', spell: 'dexterity.i', item: 'head dex1' },
{ slot: 'head', spell: 'combat.i', item: 'head combat1' },
{ slot: 'head', spell: 'strength.i', item: 'head str1' },
]
The ideal output would be something like
[
[
{ slot: 'body', spell: 'combat.i', item: 'body combat1' },
{ slot: 'legs', spell: 'dexterity.i', item: 'legs dex1' },
{ slot: 'head', spell: 'strength.i', item: 'head str1' },
],
[
{ slot: 'body', spell: 'combat.i', item: 'body combat2' },
{ slot: 'legs', spell: 'dexterity.i', item: 'legs dex1' },
{ slot: 'head', spell: 'strength.i', item: 'head str1' },
],
[
{ slot: 'body', spell: 'strength.i', item: 'body str' },
{ slot: 'legs', spell: 'dexterity.i', item: 'legs dex1' },
{ slot: 'head', spell: 'combat.i', item: 'head combat1' },
],
...etc
]
so that the final product would be all the combinations of each slot/spell/item without any repeats (disregarding the order).
My first thought was to organize the data into an a object for each slot and inside there an array for each effect.
const generateList = (data, slots, effects) => {
const matches = {};
slots.forEach(slot => {
matches[slot] = {};
effects.forEach(effect => {
matches[slot][effect] = data.filter(item => item.slot === slot && item.spell === effect);
})
});
return matches
};
Which generates
{
body: {
'combat.i': [
{ slot: 'body', spell: 'combat.i', item: 'body combat1' },
{ slot: 'body', spell: 'combat.i', item: 'body combat2' }
],
'strength.i': [ { slot: 'body', spell: 'strength.i', item: 'body str1' } ],
'dexterity.i': [ { slot: 'body', spell: 'dexterity.i', item: 'body dex1' } ]
},
legs: {
'combat.i': [ { slot: 'legs', spell: 'combat.i', item: 'legs combat1' } ],
'strength.i': [ { slot: 'legs', spell: 'strength.i', item: 'legs str1' } ],
'dexterity.i': [ { slot: 'legs', spell: 'dexterity.i', item: 'legs dex1' } ]
},
head: {
'combat.i': [ { slot: 'head', spell: 'combat.i', item: 'head combat1' } ],
'strength.i': [ { slot: 'head', spell: 'strength.i', item: 'head str1' } ],
'dexterity.i': [ { slot: 'head', spell: 'dexterity.i', item: 'head dex1' } ]
},
]
I'm now kinda stuck on how to generate all the permutations to create the desired output, especially knowing that this will need to scale up to much larger numbers. I know the answer is something to do with recursion but for the life of me, my silly front-end brain can't figure it out. Any help would be appreciated!
Keep it short and simple:
Now to make this more generic for arbitrary combination sizes, you can use recursion instead of nesting the loops, but it gets a bit more complicated:
Just ensure that the
itemscontain more unique slot values and more unique spell values than the chosensize, or you'll get no results.Finally, to make it generic over the properties that should be distinct between them items of one combination, you can introduce a parameter for those as well: