简体   繁体   中英

JavaScript convert object with specific structure to arrays

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'} ]

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

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM