'Loop or map array inside the JavaScript object

I have an array of javascript objects like:

const arrayData = [
{ name: "campaign 1", date: "2022-05-13", milestones:[{name:"Planning", targetDate: "2022-05-25"},
                                                      {name:"Funding", targetDate: "2022-05-30"},
                                                      {name:"Delievery", targetDate: "2022-05-31"}]
},

{ name: "campaign 2", date: "2022-06-19", milestones:[{name:"Planning", targetDate: "2022-08-12"},
                                                      {name:"Funding", targetDate: "2022-09-01"},
                                                      {name:"Delievery", targetDate: "2022-06-08"}]
},

{ name: "campaign 3", date: "2022-07-11", milestones:[{name:"Planning", targetDate: "2022-06-13"},
                                                      {name:"Funding", targetDate: "2022-07-10"},
                                                      {name:"Delievery", targetDate: "2022-08-01"}]
},
];

I want to convert it into this form:

const arrayData = [
{ name: "campaign 1", date: "2022-05-13", Planning:"2022-05-25", Funding: "2022-05-30", Delievery: "2022-05-31"},
{ name: "campaign 2", date: "2022-06-19", Planning: "2022-08-12", Funding: "2022-09-01", Delievery: "2022-06-08"},
{ name: "campaign 3", date: "2022-07-11", Planning: "2022-06-13", Funding: "2022-07-10", Delievery: "2022-08-01"}
];

I tried to do it this way:

let newData = [];
for (let i in arrayData) {
        newData.push({
          campaignName: arrayData[i].campaignName,
          date: arrayData[i].date,
          arrayData[i].milestones.map(item, index)=>(
            [arrayData[i].milestones[j].name]:
            arrayData[i].milestones[j].targetedDate,
          )
        });
      }

But, it didn't work for me. Kindly provide the solutions of it. Thanks



Solution 1:[1]

This will iterate the milestone property only once for each object. That would be faster.

const arrayData=[{name:"campaign 1",date:"2022-05-13",milestones:[{name:"Planning",targetDate:"2022-05-25"},{name:"Funding",targetDate:"2022-05-30"},{name:"Delievery",targetDate:"2022-05-31"}]},{name:"campaign 2",date:"2022-06-19",milestones:[{name:"Planning",targetDate:"2022-08-12"},{name:"Funding",targetDate:"2022-09-01"},{name:"Delievery",targetDate:"2022-06-08"}]},{name:"campaign 3",date:"2022-07-11",milestones:[{name:"Planning",targetDate:"2022-06-13"},{name:"Funding",targetDate:"2022-07-10"},{name:"Delievery",targetDate:"2022-08-01"}]}];

const formattedData = arrayData.map( obj => {

  const tempObj = {
    name: obj.name,
    date: obj.date
  }
  
  obj.milestones.forEach(milestone => {
    tempObj[milestone.name] = milestone.targetDate;
  });
  
  return tempObj;
});

console.log(formattedData);

Solution 2:[2]

Use Array#map and object destructuring as in the following demo. This demo assumes that the milestones elements are always in the order Planning, Funding, Delivery. If the order is bound to be different, I'll provide a second demo that would work for whatever order they appear in.

const arrayData = [ { name: "campaign 1", date: "2022-05-13", milestones:[{name:"Planning", targetDate: "2022-05-25"}, {name:"Funding", targetDate: "2022-05-30"}, {name:"Delievery", targetDate: "2022-05-31"}] }, { name: "campaign 2", date: "2022-06-19", milestones:[{name:"Planning", targetDate: "2022-08-12"}, {name:"Funding", targetDate: "2022-09-01"}, {name:"Delievery", targetDate: "2022-06-08"}] }, { name: "campaign 3", date: "2022-07-11", milestones:[{name:"Planning", targetDate: "2022-06-13"}, {name:"Funding", targetDate: "2022-07-10"}, {name:"Delievery", targetDate: "2022-08-01"}] }],

      output = arrayData.map(
          ({milestones:[
              { targetDate:Planning },
              { targetDate:Funding },
              { targetDate:Delivery }
          ],
          ...rest}) => 
          ({...rest,Planning,Funding,Delivery})
      );
      
console.log( output );

Alternatively ....

You can use Array#map and Array#reduce as in the following demo. This should work for any order AND NUMBER of milestones.

const arrayData = [ { name: "campaign 1", date: "2022-05-13", milestones:[{name:"Planning", targetDate: "2022-05-25"}, {name:"Funding", targetDate: "2022-05-30"}, {name:"Delievery", targetDate: "2022-05-31"}] }, { name: "campaign 2", date: "2022-06-19", milestones:[{name:"Planning", targetDate: "2022-08-12"}, {name:"Funding", targetDate: "2022-09-01"}, {name:"Delievery", targetDate: "2022-06-08"}] }, { name: "campaign 3", date: "2022-07-11", milestones:[{name:"Planning", targetDate: "2022-06-13"}, {name:"Funding", targetDate: "2022-07-10"}, {name:"Delievery", targetDate: "2022-08-01"}] }],

      output = arrayData.map(
          ({milestones,...rest}) => 
          ({
              ...rest,
              ...milestones.reduce(
                  (acc,{name,targetDate}) =>
                  ({...acc, [name]: targetDate}), {}
              )
          })
      );
      
console.log( output );

As for your code ....

  1. You introduced a property campaignName that does not exist in your data
  2. Rather than use Array#map you can use Array#reduce in combination with the spread ... operator as in the following demo:

const arrayData = [ { name: "campaign 1", date: "2022-05-13", milestones:[{name:"Planning", targetDate: "2022-05-25"}, {name:"Funding", targetDate: "2022-05-30"}, {name:"Delievery", targetDate: "2022-05-31"}] }, { name: "campaign 2", date: "2022-06-19", milestones:[{name:"Planning", targetDate: "2022-08-12"}, {name:"Funding", targetDate: "2022-09-01"}, {name:"Delievery", targetDate: "2022-06-08"}] }, { name: "campaign 3", date: "2022-07-11", milestones:[{name:"Planning", targetDate: "2022-06-13"}, {name:"Funding", targetDate: "2022-07-10"}, {name:"Delievery", targetDate: "2022-08-01"}] }],

      newData = [];
      
for (let i in arrayData) {
    newData.push({
        name: arrayData[i].name,
        date: arrayData[i].date,
        ...arrayData[i].milestones.reduce(
            (acc, {name,targetDate}) =>
            ({...acc, [name]:targetDate}),{}
        )
    });           
}

console.log( newData );

Solution 3:[3]

Something like this?

arrayData.map(item => ({
    name: item.name,
    date: item.date,
    Planning: item.milestones.find(milestone => milestone.name === 'Planning')?.targetDate,
    Funding: item.milestones.find(milestone => milestone.name === 'Funding')?.targetDate,
    Delievery: item.milestones.find(milestone => milestone.name === 'Delievery')?.targetDate,
}))

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3 Gerjan