Home > Software engineering >  Converting nested arrays in JavaScript into flat objects containing members of the parent object
Converting nested arrays in JavaScript into flat objects containing members of the parent object

Time:04-21

I have an array of objects with nested subarray (empoloyees), and the names of the attributes on the parent level can be voluntary (for example, company):

values = [{
  company: 'DotCom',
  employees: [{
    name: 'John Doe',
    position: 'Salesrep'
  }, {
    name: 'Mike Pen',
    position: 'Driver'
  }]
}, {
  company: 'Green Tree',
  employees: [{
    name: 'Suzanne Fox',
    position: 'Secretary'
  }, {
    name: 'Kelly Fun',
    position: 'CEO Assistant'
  }, {
    name: 'Brian Bush',
    position: 'CEO'
  }]
}]

I need to transform it in a way that the resulting objects will not contain nested arrays:

[{
    company: "DotCom",
    name: "John Doe",
    position: "Salesrep"
  },
  {
    company: "DotCom",
    name: "Mike Pen",
    position: "Driver"
  },
  {
    company: "Green Tree",
    name: "Suzanne Fox",
    position: "Secretary"
  },
  {
    company: "Green Tree",
    name: "Kelly Fun",
    position: "CEO Assistant"
  },
  {
    company: "Green Tree",
    name: "Brian Bush",
    position: "CEO"
  }
]

This is my code:

values = [{company: 'DotCom', employees: [{name: 'John Doe', position: 'Salesrep'}, {name: 'Mike Pen', position: 'Driver'}]},{company: 'Green Tree', employees: [{name: 'Suzanne Fox', position: 'Secretary'}, {name: 'Kelly Fun', position: 'CEO Assistant'}, {name: 'Brian Bush', position: 'CEO'}]}]


const getEntries = (o) =>
  Object.entries(o).flatMap(([k, v]) =>
    Object(v) === v ? getEntries(v, k) : [
      [k, v]
    ]
  )

var result = []
values.map(item => [item].flatMap(x => result.push(Object.fromEntries(getEntries(x)))))

console.log(result)

And the result is (console.log(result)) giving me only the one (last) member of the nested array of employees, and not all of the employees:

[{
    company: "DotCom",
    name: "Mike Pen",
    position: "Driver"
  },
  {
    company: "Green Tree",
    name: "Brian Bush",
    position: "CEO"
  }
]

What would be the best approach to modify the code so that I would get all of the employees into the result?

Here is another example of the values array:

values = [{
  city: 'New York', 
  division: 'Main Office', 
  employees: [{
    name: 'John Doe', 
    position: 'Salesrep'
  }, {
    name: 'Mike Pen', 
    position: 'Driver'
  }]
},{
  city: 'Tampa', 
  division: 'Regional Office', 
  employees: [{
    name: 'Suzanne Fox', 
    position: 'Secretary'
  }, {
    name: 'Kelly Fun', 
    position: 'CEO Assistant'
  }, {
    name: 'Brian Bush', 
    position: 'CEO'
  }]
}]

The expected result:

[{
  city: 'New York', 
  division: 'Main Office', 
  name: 'John Doe', 
  position: 'Salesrep'
 }, 
 {...}]

CodePudding user response:

Do NOT use map or flatMap if you do not use the resulting array.

Here I use flatMap and spread to return a flattened map

Without names - assuming only ONE array and no other nesting

const values = [{company: 'DotCom', employees: [{name: 'John Doe', position: 'Salesrep'}, {name: 'Mike Pen', position: 'Driver'}]},{company: 'Green Tree', employees: [{name: 'Suzanne Fox', position: 'Secretary'}, {name: 'Kelly Fun', position: 'CEO Assistant'}, {name: 'Brian Bush', position: 'CEO'}]}]

const companyArr = values
  .flatMap(item => {
    const obj = {};
    let arr = [];
    Object.entries(item).forEach(([key,val]) => {
      if (Array.isArray(val)) arr = val;
      else obj[key] = val;
    })
    return arr.map(item => ({...obj,...item}))
 });
console.log(companyArr)

Using the names

const values = [{company: 'DotCom', employees: [{name: 'John Doe', position: 'Salesrep'}, {name: 'Mike Pen', position: 'Driver'}]},{company: 'Green Tree', employees: [{name: 'Suzanne Fox', position: 'Secretary'}, {name: 'Kelly Fun', position: 'CEO Assistant'}, {name: 'Brian Bush', position: 'CEO'}]}]


const empArr = values
  .flatMap(entry => entry.employees
    .map(emp => ({"company": entry.company, ...emp}))
  );
console.log(empArr)

CodePudding user response:

Please check if this would work for you. I am spreading the employee object and flattening the resultant array:

let values = [{
  company: 'DotCom',
  employees: [{
    name: 'John Doe',
    position: 'Salesrep'
  }, {
    name: 'Mike Pen',
    position: 'Driver'
  }]
}, {
  company: 'Green Tree',
  employees: [{
    name: 'Suzanne Fox',
    position: 'Secretary'
  }, {
    name: 'Kelly Fun',
    position: 'CEO Assistant'
  }, {
    name: 'Brian Bush',
    position: 'CEO'
  }]
}];

let newValues = values.map(c => c.employees.map(e => {
  return {
    company: c.company,
    ...e
  }
})).flatMap(x => x);

console.log(newValues);

  • Related