Home > Net >  Generate multi child objects from parent object with array fields change
Generate multi child objects from parent object with array fields change

Time:11-05

If I have an object parent like this, and an object with every field name is the ID which include the array like childs. How can I do to have clone the parent become children with different attritube as the result I mention below?

var parent = {
    'Name': 'Product ABC',
}

var attributes = {
    // AttributeId : Name
    'ID0001': ['Black', 'Red'],
    'ID0002': ['Small', 'Medium', 'Large'],
    'ID0003': ['Cotton', 'Len']
}

The children cloned should be

{
    'Name': 'Product ABC', // Same as parent
    'Attributes': [ // Black - Small - Cotton
        {'AttributeId':'ID0001', value:'Black'},
        {'AttributeId':'ID0002', value:'Small'}
        {'AttributeId':'ID0003', value:'Cotton'}
    ]
},
{
    'Name': 'Product ABC', // Same as parent
    'Attributes': [ // Red - Small - Cotton
        {'AttributeId':'ID0001', value:'Red'},
        {'AttributeId':'ID0002', value:'Small'}
        {'AttributeId':'ID0003', value:'Cotton'}
    ]
},
{
    'Name': 'Product ABC', // Same as parent
    'Attributes': [ // Black - Medium - Cotton
        {'AttributeId':'ID0001', value:'Black'},
        {'AttributeId':'ID0002', value:'Medium'}
        {'AttributeId':'ID0003', value:'Cotton'}
    ]
}
.....

P/S It seem to hard to understand the values rule of the children generated. Here is my description: children is cloned to become full of atributes in the 'attributes' object that include some arrays, but it unique atribute. like 'Black - Small - Cotton', 'Red - Small - Cotton', 'Black - Medium - Cotton', 'Black - Medium - Len', ...

CodePudding user response:

This looks like a Cartesian product that is then mapped later, so I have used this answer to get the Cartesian product of the attributes (read: "combinations"). Then I map over the resulting combinations and transform them into the desired structure.

const parent = {
    'Name': 'Product ABC',
};

const children = {
    'ID0001': ['Black', 'Red'],
    'ID0002': ['Small', 'Medium', 'Large'],
    'ID0003': ['Cotton', 'Len'],
};

const f = (a, b) => [].concat(...a.map(a => b.map(b => [].concat(a, b))));
const cartesian = (a, b, ...c) => b ? cartesian(f(a, b), ...c) : a;

function combinations(attributes) {
    // restructure the given attributes
    const choices = Object
        .entries(attributes)
        .map(([key, value]) => value.map((attr) => ({ [key]: attr })));
    // get cartesian product of the choices
    return cartesian(...choices);
}

const results = combinations(children).map((combo) => ({
    ...parent,
    Attributes:
        combo.map((o) => {
            const key = Object.keys(o)[0]; // get only key
            return {
                AttributeId: key,
                value: o[key],
            };
        }),
}));

console.log(results);
.as-console-wrapper { max-height: 100% !important }

CodePudding user response:

Here is some psuedocode that can hopefully get you started:

Just to be clear - this code is just an example of the logic you would need to do this. It is not actually finished code in a particular language. Actually writing code oneself in a coding language is a key aspect of learning to code and learning a particular coding language

listOfProducts = []
valueIndexes = list.of(0).length(attribute.length)
while true

  // initialize product
  product = {'name': productName, 'attributes': []}

  // add all attributes based on current value indexes
  for attribute with index in childs
    product[attributes][attribute.name] = {'Attribute': attribute.name, 'value' : attribute[valueIndexes[index]]}

  // add product to list
  listOfProducts.add(product)

  // update current indexes 
  var i = 0
  var finished = false
  while true
    valueIndexes[i]  = 1

    // if we have no more values at this depth left, increase depth
    if (valueIndexes[i] >= attributes[i].length)
       valueIndexes[i] = 0
       i  

       // if we we have no farther to go we are done
       if (i > valueIndexes.length)
          finished = true
          break
       
     else
       break

  // break if we are done
  if finished
    break

  • Related