Home > Back-end >  How can I create several arrays on each of the values of other array of objects?
How can I create several arrays on each of the values of other array of objects?

Time:06-28

So currently I have this array structure:

const object = {
  object1: ["01", "02"],
  object2: ["item1", "item2", "item3"],
  object3: ["product1", "product2"]
}

and I need to transform it to:

const array = [
  {
    object1: "01",
    object2: "item1",
    object3: "product1",
  }, {
    object1: "02",
    object2: "item1",
    object3: "product1",
  }, {
    object1: "01",
    object2: "item2",
    object3: "product1",
  }, {
    object1: "01",
    object2: "item3",
    object3: "product1",
  }, {
    object1: "02",
    object2: "item2",
    object3: "product1",
  }, {
    object1: "02",
    object2: "item3",
    object3: "product1",
  }, {
    object1: "01",
    object2: "item1",
    object3: "product2",
  }, {
    object1: "02",
    object2: "item1",
    object3: "product2",
  }, {
    object1: "02",
    object2: "item2",
    object3: "product2",
  }, {
    object1: "03",
    object2: "item2",
    object3: "product2",
  },
]

So basically I need to create a new array based off of each combination on the initial object of arrays, and the initial array the be on the thousands of items.

This is what I have so far but no luck getting the structure I need.

const object = {
  object1: ["01", "02"],
  object2: ["item1", "item2", "item3"],
  object3: ["product1", "product2"]
}
const arr = []
Object.entries(object).forEach((element, i) => {
  element.forEach((innerElement, j) => {
    let _element = {[`${element[0]}`]:element[1][j]}
    arr.push(_element)
  })
});

console.log("map", arr)

Is there any way to transform the data to the structure I need it? Thanks in advance!

CodePudding user response:

I'd suggest creating a generic solution that will iterate over the possible properties and values of the template object and create an array of all possible outcomes.

We'd create a addPossibleValues() function than will expand the array of objects for each key in the template object. Each round will increase the number of objects by the successive length of the relevant property array.

const object = {
  object1: ["01", "02"],
  object2: ["item1", "item2", "item3"],
  object3: ["product1", "product2"]
}

function addPossibleValues(arr, property, possibleValues) {
    return possibleValues.flatMap(v => { 
        return (arr.length ? arr: [{}]).map(x => { 
            return { ...x, [property]: v};
        })
    });
}

let result = [];
for(let key in object) {
    result = addPossibleValues(result, key, object[key]);
}

console.log('Result:', result)
.as-console-wrapper { max-height: 100% !important; }

You could also do this using a Array.reduce() call:

const object = {
  object1: ["01", "02"],
  object2: ["item1", "item2", "item3"],
  object3: ["product1", "product2"]
}

function addPossibleValues(arr, property, possibleValues) {
    return possibleValues.flatMap(v => { 
        return (arr.length ? arr: [{}]).map(x => { 
            return { ...x, [property]: v};
        })
    });
}

let result = Object.keys(object).reduce((acc, key) => {
    return addPossibleValues(acc, key, object[key]);
}, []);
console.log('Result:', result)
.as-console-wrapper { max-height: 100% !important; }

CodePudding user response:

Idea

Step-wise generation of the cross product of the arrays in the original object:

  • Iterate through all of the original object properties.

  • Consider some iteration.

  • Assume that we have an interim array filled in the previous iterations

  • For each of the values cv of the array stored as the current iteration's property cp in the original object ...

    • take each object from the interim result array
    • clone it
    • add a property cp to the cloned object nd fill it with the value cv.
    • add the clone to the result array
  • conclude the iteration by removing the originals of the coning operation from the result array (these are now obsolete as they arethe cross product of one dimension less).

  • Initialize the while procedure with an array with a single empty object

Code

const object = {
  object1: ["01", "02"],
  object2: ["item1", "item2", "item3"],
  object3: ["product1", "product2"]
}


let a_res = [{}];
for (s_key in object) {
    let n_currentCount = a_res.length
      ;
          
    object[s_key].forEach ( ps_item => {
        for (let i = 0; i < n_currentCount; i  ) {
            let o_new = Object.assign({ [s_key]: ps_item }, a_res[i])
              ;
              
            a_res.push(o_new);
        }
    });

    a_res.splice(0, n_currentCount); // in situ
}
console.log(a_res);

CodePudding user response:

First, I must apologize about my English. You could use 3 nested forEach.

const object = {
  object1: ["01", "02"],
  object2: ["item1", "item2", "item3"],
  object3: ["product1", "product2"]
}

var arr = []

object.object3.forEach(o3 => 
  object.object2.forEach(o2 =>
    object.object1.forEach(o1 => 
      arr.push({object1: o1, object2: o2, object3: o3}))));
      
console.log(arr);

Change the order of the forEach if you prefer to change the order of the combinations

  • Related