0

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'
 }, 
 {...}]
5
  • 1
    How do I format my posts using Markdown or HTML? Commented Apr 21, 2022 at 7:49
  • 1
    "What would be the best approach..." - Without an explanation what "best" means exactly, you will only get opinions -> What topics can I ask about here?. Commented Apr 21, 2022 at 7:51
  • "...get all of the employees into the result" - What have you done so far to solve this on your own? Commented Apr 21, 2022 at 7:51
  • Thank you @mplungjan, how do you think is there a way to achieve this without using foreach? Commented Apr 21, 2022 at 8:08
  • Please give us two different examples and their output if your key names differ Commented Apr 21, 2022 at 8:26

2 Answers 2

1

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

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

1 Comment

thank you. If I don't know in advance the non-array member names at the parent level, can I get rid of hard-coding them (e.g. company: c.company)?
0

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)

3 Comments

Thanks @mplungjan this will certainly work if you know the key names but I need a more universal solution as the object members names are not pre-determined so I don't really know in advance what would be the key names but I should be checking if the member of a parent object is an array and if so I need to do the transform. But I know the name of the nested array object (employees)
That would have been useful to know from your question.
@BratBear See new version

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.