1

Expected input:

const all = [
       {  "Attribute_Values" : [ "36", "38", "40" ],
          "Attribute" : "size"
       }, 
       {  "Attribute_Values" : [ "blue", "black" ],
          "Attribute" : "color"
       }
    ];

Expected output:

[ {size: '36', color: 'blue'},
  {size: '36', color: 'black'},
  {size: '38', color: 'blue'},
  {size: '38', color: 'black'}, 
  {size: '40', color: 'blue'},
  {size: '40', color: 'black'} ]
0

3 Answers 3

4

First generate an object with wanted keys and values, then take a recursive function which separates all key/value pairs and build a new cartesian product by iterating the values, if an array with objects call getCartesian again and build new objects.

This works for nested objects as well.

function getCartesian(object) {
    return Object.entries(object).reduce((r, [k, v]) => {
        var temp = [];
        r.forEach(s =>
            (Array.isArray(v) ? v : [v]).forEach(w =>
                (w && typeof w === 'object' ? getCartesian(w) : [w]).forEach(x =>
                    temp.push(Object.assign({}, s, { [k]: x }))
                )
            )
        );
        return temp;
    }, [{}]);
}

var all = [{ Attribute_Values: ["36", "38", "40"], Attribute: "size" }, { Attribute_Values: ["blue", "black"], Attribute: "color" }],
    temp = Object.assign(...all.map(({ Attribute_Values, Attribute }) => ({ [Attribute]: Attribute_Values }))),
    cartesian = getCartesian(temp);

console.log(temp);
console.log(cartesian);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Sign up to request clarification or add additional context in comments.

1 Comment

I like your deconstruction of the main object to assign it to a new, more json-like object
1

I would go with a cartesian product generator which takes the attribute values, and while filling the result read the attribute name from the products current position. Generator is taken from here

const all = [
       {  "Attribute_Values" : [ "36", "38", "40" ],
          "Attribute" : "size"
       }, 
       {  "Attribute_Values" : [ "blue", "black" ],
          "Attribute" : "color"
       }
    ];

// Cartesian generator - copied from https://stackoverflow.com/a/44012184/3820185
function* cartesian(head, ...tail) {
  const remainder = tail.length > 0 ? cartesian(...tail) : [[]];
  for (let r of remainder) for (let h of head) yield [h, ...r];
}

let result = [], part, product, i;

for(product of cartesian(...all.map(i => i.Attribute_Values))) {
  part = {};
  for(i = 0; i < product.length; i++) part[all[i].Attribute] = product[i];
  result.push(part);
}

console.log(result);

Comments

0

You can iterate over the sizes array and then combine every size with every color by iterating over the colors array.

const all = [
       {  "Attribute_Values" : [ "36", "38", "40" ],
          "Attribute" : "size"
       }, 
       {  "Attribute_Values" : [ "blue", "black" ],
          "Attribute" : "color"
       }
    ];
    
 let results = [];
 
all[0].Attribute_Values.forEach(size => {
  all[1].Attribute_Values.forEach(color => {
    results.push({size: size, color: color});
   });
});

console.log(results);
 
 

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.