0

I have two arrays of objects, and I want to update the data in the first array if there is a similar data in the second array. I tried using forEach, but I get an error after looping through the second element of the response array.

First array of objects:

const body = [{
    slot: "9:00",
    status: "Available",
    clientName: "",
    doctorName: ""
  }, {
    slot: "9:30",
    status: "Available",
    clientName: "",
    doctorName: ""
  }, {
    slot: "1:00",
    status: "Available",
    clientName: "",
    doctorName: ""
  }, {
    slot: "1:30",
    status: "Available",
    clientName: "",
    doctorName: ""
  }
]

Second array of objects:

const response = [{
  clientName: "John Doe",
  doctorName: "Paul Pierce",
  slot: "09:00",
  status: "Not Available"
}, {
  clientName: "James Bond",
  doctorName: "Chris Paul",
  slot: "01:00",
  status: "Not Available"
}]

This is my desired output:

const result = [{
    slot: "9:00",
    status: "Not Available",
    clientName: "John Doe",
    doctorName: "Paul Pierce"
  }, {
    slot: "9:30",
    status: "Available",
    clientName: "",
    doctorName: ""
  }, {
    slot: "1:00",
    status: "Not Available",
    clientName: "James Bond",
    doctorName: "Chris Paul"
  }, {
    slot: "1:30",
    status: "Available",
    clientName: "",
    doctorName: ""
  }
]
YukiOno
  • 21
  • 5
  • *"I tried using forEach, but I get an error..."*: please provide your code. – trincot Mar 12 '23 at 10:23
  • And the error as well – Nasser Kessas Mar 12 '23 at 10:27
  • Why do you have two different formats for the slots? You should fix this at the source of your data. – trincot Mar 12 '23 at 10:30
  • or [How do you update an object in an array based on another array?](https://stackoverflow.com/questions/73074784/how-do-you-update-an-object-in-an-array-based-on-another-array) or [Update object in array from another object in array](https://stackoverflow.com/questions/55757916/update-object-in-array-from-another-object-in-array) or [Update an array using another array based on matched property value](https://stackoverflow.com/questions/71174291/update-an-array-using-another-array-based-on-matched-property-value) – pilchard Mar 12 '23 at 10:50
  • also [Merge 2 arrays of objects](https://stackoverflow.com/questions/7146217/merge-2-arrays-of-objects) – pilchard Mar 12 '23 at 10:53

4 Answers4

1

For each element in body, find the corresponding info in response. If not found, return original one without modifying; else, merge them and return a new object.

As @trincot has pointed out, the data has two different time formats. I deal with this using String#padStart; however, it is best that they be modified at the source.

body.map(originalSlot => {
    const slotInfo = response.find(
      ({ slot }) => slot === originalSlot.slot.padStart(5, 0)
    );

    if (!slotInfo) {
        return originalSlot;
    }

    return { ...originalSlot, ...slotInfo, slot: originalSlot.slot };
});

Try it:

const body = [
  {
    slot: '9:00',
    status: 'Available',
    clientName: '',
    doctorName: ''
  },
  {
    slot: '9:30',
    status: 'Available',
    clientName: '',
    doctorName: ''
  },
  {
    slot: '1:00',
    status: 'Available',
    clientName: '',
    doctorName: ''
  },
  {
    slot: '1:30',
    status: 'Available',
    clientName: '',
    doctorName: ''
  }
];

const response = [
  {
    clientName: 'John Doe',
    doctorName: 'Paul Pierce',
    slot: '09:00',
    status: 'Not Available'
  },
  {
    clientName: 'James Bond',
    doctorName: 'Chris Paul',
    slot: '01:00',
    status: 'Not Available'
  }
];

const results = body.map(originalSlot => {
    const slotInfo = response.find(
    ({ slot }) => slot === originalSlot.slot.padStart(5, 0)
  );

    if (!slotInfo) {
        return originalSlot;
    }

    return { ...originalSlot, ...slotInfo, slot: originalSlot.slot };
});

console.log(results);
InSync
  • 4,851
  • 4
  • 8
  • 30
0

Assuming you change the response array slot times to match the format of the body (if you choose not to this, you can use the method used by @Aniket Raj in his answer to compare the times):

You could use this very simple self-explanatory method:

let result = [...body];

for (let time of body) {
    let responseSlot = response.find(s => s.slot == time.slot);

    if (responseSlot) {
        result = [...result.filter(t => t != time), responseSlot];
    }
}

Which outputs the following:

[
  { slot: '9:30',
    status: 'Available',
    clientName: '',
    doctorName: ''
  },
  { slot: '1:30',
    status: 'Available',
    clientName: '',
    doctorName: ''
  },
  {
    clientName: 'John Doe',
    doctorName: 'Paul Pierce',
    slot: '9:00',
    status: 'Not Available'
  },
  {
    clientName: 'James Bond',
    doctorName: 'Chris Paul',
    slot: '1:00',
    status: 'Not Available'
  }
]

That is you change response array to this:

const response = [{
    clientName: "John Doe",
    doctorName: "Paul Pierce",
    slot: "9:00",
    status: "Not Available"
}, {
    clientName: "James Bond",
    doctorName: "Chris Paul",
    slot: "1:00",
    status: "Not Available"
}]
Nasser Kessas
  • 359
  • 1
  • 13
0

Here you can try this logic :

const first = [
  {
    slot: "9:00",
    status: "Available",
    clientName: "",
    doctorName: "",
  },
  {
    slot: "9:30",
    status: "Available",
    clientName: "",
    doctorName: "",
  },
  {
    slot: "1:00",
    status: "Available",
    clientName: "",
    doctorName: "",
  },
  {
    slot: "1:30",
    status: "Available",
    clientName: "",
    doctorName: "",
  },
];

const second = [
  {
    clientName: "John Doe",
    doctorName: "Paul Pierce",
    slot: "9:00",
    status: "Not Available",
  },
  {
    clientName: "James Bond",
    doctorName: "Chris Paul",
    slot: "1:00",
    status: "Not Available",
  },
];

// To solve problem for 09:01 or 9:01
function timeStringChecker(timeStr) {
  let [leftStr, rightStr] = timeStr.split(":");
  return +(leftStr + rightStr);
}

first.forEach((elem) =>
  second.some((elem2) => {
    if (timeStringChecker(elem.slot) == timeStringChecker(elem2.slot)) {
      Object.assign(elem, elem2);
    }
  })
);

console.log(first);
Jerry
  • 1,005
  • 2
  • 13
0

As mentioned from a previous post this is what you are looking for:

const result = [];
Object.keys(body).forEach((key) =>
  key in response ? (result[key] = response[key]) : (result[key] = body[key])
);

The logic here is that you parse all the properties of the body object and if the property value matched with the response object property value it will overwrite the value of the property for the body object. Otherwise it just keep the values of the specific body object as it is.

Link to previous post: Update an object with matching properties and ignore new properties

PTsag
  • 108
  • 2
  • 9