Reputation: 181
I'm struggling with some algorithm with javascript. I'm using Vue as framework and state managament. I have an object that needs to be 'calculated' as variants.
For example, I have 3 objects and in those objects some values as array, like so:
"attributes":[
{
"title":{
"text":"Size",
"value":"1"
},
"values":[
"M",
"L",
"X"
]
},
{
"title":{
"text":"Color",
"value":"2"
},
"values":[
"Red",
"Green",
"Black"
]
},
{
"title":{
"text":"Material"
},
"values":[
"Cotton",
]
}
]
So my state for this is obviously attributes. So what I really need to do is to foreach attribute values and create variant for every possible combination, and console.log them. Like so:
M/Red/Cotton, L/Red/Cotton, X/Red/Cotton, M/Green/Cotton, L/Green/Cotton, X/Green/Cotton, M/Black/Cotton, L/Black/Cotton, X/Black/Cotton
So I started function that will only foreach attributes, so I need to foreach values and make that codes (up) for them, but no idea how to proceed. So it looks like:
addVariant: function (text) {
this.attributes.forEach(element => console.log(element));
},
Upvotes: 0
Views: 369
Reputation: 447
So basically you want to make combinations of attribute.values right? Here's an answer I found for making combinations with arrays of javascripts. https://stackoverflow.com/a/47701395/13095249 I'm not sure how that works I just copied the code.
Coming back to your problem, I would make an array for all attribute.values like
parts = attributes.map(attribute => attribute.values)
and run the code in above answer should give you the desired output
parts.reduce((a, b) => a.reduce((r, v) => r.concat(b.map(w => [].concat(v, w))), []));
your addVariant function could look like:
addVariant: function (text) {
const parts = this.attributes.map(attribute => attribute.values);
const combinations = parts.reduce((a, b) => a.reduce((r, v) => r.concat(b.map(w => [].concat(v, w))), []));
console.log(combinations)
},
Upvotes: 2
Reputation: 1347
Sounds like you want the cartesian product
For your specific case, this is probably what you're looking for,
addVariant: function (text) {
let cartesian = (...a) => a.reduce((a, b) => a.flatMap(d => b.map(e => [d, e].flat())), []);
let values = this.attributes.map(attr => attr.values);
let combinations = cartesian(...values).map(v => v.join('/'));
console.log(combinations);
},
Upvotes: 4
Reputation: 22574
You can use array#reduce
with array#map
and array#flatMap
to generate cartesian product of values
.
const attributes = [ { "title":{ "text":"Size", "value":"1" }, "values":[ "M", "L", "X" ] }, { "title":{ "text":"Color", "value":"2" }, "values":[ "Red", "Green", "Black" ] }, { "title":{ "text":"Material" }, "values":[ "Cotton", ] } ],
result = attributes.reduce((r, o, i) => {
const array = o.values.map(v => v);
return i ? array.flatMap(v => r.map(w => (w + '\\' + v))): array;
},[]);
console.log(result.join());
.as-console-wrapper { max-height: 100% !important; top: 0; }
Upvotes: 2