Home > other >  How to convert multiple objects in an array to a new object?
How to convert multiple objects in an array to a new object?

Time:11-16

Let's say I got an Array below:

[
  { type: 'senior', schoolName: 'school-A', country: 'America' },
  { type: 'senior', schoolName: 'school-B', country: 'England' },
  { type: 'junior', schoolName: 'school-C', country: 'German' },
  { type: 'junior', schoolName: 'school-D', country: 'Italy' }, 
]

How can I convert the array above to an object as shown in below:

{
  senior: {
    America: 'school-A', 
    England: 'school-B'
  }, 
  junior: {
    German: 'school-C', 
    Italy: 'school-D'
  }
}

What is the syntactically cleanest way to accomplish this?

Thanks for any help!!

CodePudding user response:

One way could be to reduce your array of objects to a single object. For each iteration you can accumulate your object (initially starting as an empty object {}), to contain the current type key along with the new key-value pair for the country and schoolName. By using the spread syntax ... you can merge the previously seen object at the type key (from your current accumulated object) with the new object you're constructing.

See code comments in the example below:

const arr = [ { type: 'senior', schoolName: 'school-A', country: 'America' }, { type: 'senior', schoolName: 'school-B', country: 'England' }, { type: 'junior', schoolName: 'school-C', country: 'German' }, { type: 'junior', schoolName: 'school-D', country: 'Italy' }, ];

const res = arr.reduce((acc, {type, schoolName, country}) => ({ // obtain the kys from the current object using destructuring assignment
  ...acc, // merge the current object stored in acc into the current object `{}` we're building
  [type]: { // using "computed property names"
    ...acc[type], // merge inner object (still worrks when acc[type] === undefined) 
    [country]: schoolName
  }
}), {}); // start with an initial empty object `{}` that we'll accumulate to
console.log(res);
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

Spreading your object each iteration could be seen as inefficient, so you can accumulate the single object reference instead (which at this point, might be worth looking at using a standard for loop for readability instead):

const arr = [ { type: 'senior', schoolName: 'school-A', country: 'America' }, { type: 'senior', schoolName: 'school-B', country: 'England' }, { type: 'junior', schoolName: 'school-C', country: 'German' }, { type: 'junior', schoolName: 'school-D', country: 'Italy' }, ];

const res = arr.reduce((acc, {type, schoolName, country}) => {
  if(!acc[type]) acc[type] = {};
  acc[type][country] = schoolName;
  return acc;
}, {});
console.log(res);
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

I think this is a simple and readable solution to your problem (if multiple instances of the same country show up in the same type the last occurence will override all previous occurences)

let data = [
  { type: 'senior', schoolName: 'school-A', country: 'America' },
  { type: 'senior', schoolName: 'school-B', country: 'England' },
  { type: 'junior', schoolName: 'school-C', country: 'German' },
  { type: 'junior', schoolName: 'school-D', country: 'Italy' }, 
];

let res = {};

data.forEach(e => {
  if(!res[e.type])
    res[e.type] = {};
    
  res[e.type][e.country] = e.schoolName;
});

console.log(res);
<iframe name="sif3" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related