0

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));
        },

3 Answers 3

4

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);
},
Sign up to request clarification or add additional context in comments.

2 Comments

That could be the answer, but when I'm testing it says that "TypeError: Cannot read property 'flatMap' of undefined
a.reduce((a, b) => a.flatMap(d => b.map(e => [d, e].flat()))) is missing a start a value as second argument to reduce. a.reduce((a, b) => a.flatMap(d => b.map(e => [d, e].flat())), [])
2

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; }

4 Comments

This is exactly what I need! Only problem is when I try to add my values from states, it's giving that map is undefined.
Sounds like your state have some objects which has missing values array. You can use o.values?.map(v => v)
result.join() will return a string, try mapping the result only.
Thank you very much! It was mistake on my side, now it's working perfectly!
2

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)
},

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.