I'm creating data per day and I'm dealing with following response data ...
{
tipster: {
name: "Gallita FC",
description: "TEST",
picks: [{
date: "Friday, February 18th 2022",
data: [{
title: "yesterday",
description: "TEST",
date: "Friday, February 18th 2022",
category: "NHL",
pickImageUrl: "https://res.cloudinary.com/creaciones-inteligentes-roy/image/upload/v1644455039/Captura_de_Pantalla_2022-02-09_a_la_s_18.59.43_voy1pj.png",
}],
}, {
date: "Saturday, February 19th 2022",
data: [{
title: "today",
description: "TEST",
date: "Saturday, February 19th 2022",
category: "NHL",
pickImageUrl: "https://res.cloudinary.com/creaciones-inteligentes-roy/image/upload/v1644455039/Captura_de_Pantalla_2022-02-09_a_la_s_18.59.43_voy1pj.png",
}],
}],
imageUrl: "https://res.cloudinary.com/sports-master/image/upload/v1644649610/27ADF778-454B-4DB7-88B7-DC98202E2736_utb7xw.png",
bannerUrl: "https://scontent.fmex34-1.fna.fbcdn.net/v/t1.6435-9/167022015_1317341031983063_7337313589197318410_n.jpg?_nc_cat=111&ccb=1-5&_nc_sid=a26aad&_nc_ohc=5ctqP2nFf7IAX94PNSO&_nc_ht=scontent.fmex34-1.fna&oh=00_AT_TzRHhhV73ji7wzW2X1u27TOU8TNlObwtp0ILc0DzC1Q&oe=62207F2C",
id: "62075e5a13a43ace611fe5bd",
},
}
Within the tipster.picks
array I need to append an additional data
item to the last matching data
item. A match could be where data.title
equals "today"
.
The code I came up with so far does not lead to the correct result ...
const newPick = {
title,
description,
date,
category,
pickImageUrl,
};
const tipsterUpdate = {
...req.body,
picks: [...tipster.picks, tipster.picks.slice(-(1)[0], newPick)],
};
I'm using spread operator because I need to maintain the old data and only add a new object on the data array.
I really appreciate a little help here. Thank you.
CodePudding user response:
Destructure out the picks
array from everything else in the tipster
object, then build a new tipster
object containing an updated picks
array.
const data={tipster:{name:"Gallita FC",description:"TEST",picks:[{date:"Friday, February 18th 2022",data:[{title:"yesterday",description:"TEST",date:"Friday, February 18th 2022",category:"NHL",pickImageUrl:"https://res.cloudinary.com/creaciones-inteligentes-roy/image/upload/v1644455039/Captura_de_Pantalla_2022-02-09_a_la_s_18.59.43_voy1pj.png"}]},{date:"Saturday, February 19th 2022",data:[{title:"today",description:"TEST",date:"Saturday, February 19th 2022",category:"NHL",pickImageUrl:"https://res.cloudinary.com/creaciones-inteligentes-roy/image/upload/v1644455039/Captura_de_Pantalla_2022-02-09_a_la_s_18.59.43_voy1pj.png"}]}],imageUrl:"https://res.cloudinary.com/sports-master/image/upload/v1644649610/27ADF778-454B-4DB7-88B7-DC98202E2736_utb7xw.png",bannerUrl:"https://scontent.fmex34-1.fna.fbcdn.net/v/t1.6435-9/167022015_1317341031983063_7337313589197318410_n.jpg?_nc_cat=111&ccb=1-5&_nc_sid=a26aad&_nc_ohc=5ctqP2nFf7IAX94PNSO&_nc_ht=scontent.fmex34-1.fna&oh=00_AT_TzRHhhV73ji7wzW2X1u27TOU8TNlObwtp0ILc0DzC1Q&oe=62207F2C",id:"62075e5a13a43ace611fe5bd"}};
const newPick = {
title: 'Bob',
description: 'Bob does it again',
date: new Date(),
category: 'Bob',
pickImageUrl: 'bobImage',
};
// Accept data, the new pick, and a search
// (in this case "today")
function addNewPick(data, newPick, search) {
// Grab the picks, and then everything else
// from the tipster object
const { tipster: { picks, ...rest } } = data;
// `find` the index of the array containing the search text
const index = picks.findIndex(pick => {
return pick.data.some(obj => {
return obj.title === search;
});
});
// Add the new pick to the "today" array
picks[index].data.push(newPick);
// Return a new tipster object with
// the updated picks
return {
tipster: { ...rest, picks }
};
}
const out = addNewPick(data, newPick, 'today');
console.log(out);
CodePudding user response:
quoting the OP
I'm using spread operator because I need to mantaint the old data and only add a new object on the data array.
Since spread syntax creates a shallow copy only, thus any nested level of the copy is still a reference and therefore in danger of being mutated, I suggest a one time deep clone via structuredClone
(there are polyfills for environments which do not yet support this Web-Api method).
And as for a generic approach, which inserts a new data item after (either) the last data with a matching condition (or even after every condition matching data item), one needs a function which gets provided
- the
tipster.picks
reference of the deeply cloned response data object, - the to be inserted new data item,
- a callback function which implements the condition of a matching data item.
Within a first step one would collect a list of all data items where the condition does match. The second step is the insert task which can be adapted to maybe changing requirements ...
function insertDataItemAfterLastMatchingCondition(picks, item, condition) {
// collect a list of all data items where `condition` matches.
const matchList = picks
.reduce((matches, pickItem) => {
const { data } = pickItem;
const index = data.findIndex(condition);
if (index >= 0) {
matches.push({ array: data, index });
}
return matches;
}, []);
// insert new item excusivley after the last matching data item.
const { array, index } = matchList.at(-1) ?? {};
if (Array.isArray(array)) {
array.splice((index 1), 0, item);
}
// // insert new item (copy) after every matching data item.
//
// matchList.forEach(({ array, index }) =>
// array.splice((index 1), 0, {...item})
// );
}
const responseData = {tipster:{name:"Gallita FC",description:"TEST",picks:[{date:"Friday, February 18th 2022",data:[{title:"yesterday",description:"TEST",date:"Friday, February 18th 2022",category:"NHL",pickImageUrl:"https://res.cloudinary.com/creaciones-inteligentes-roy/image/upload/v1644455039/Captura_de_Pantalla_2022-02-09_a_la_s_18.59.43_voy1pj.png"}]},{date:"Saturday, February 19th 2022",data:[{title:"today",description:"TEST",date:"Saturday, February 19th 2022",category:"NHL",pickImageUrl:"https://res.cloudinary.com/creaciones-inteligentes-roy/image/upload/v1644455039/Captura_de_Pantalla_2022-02-09_a_la_s_18.59.43_voy1pj.png"}]}],imageUrl:"https://res.cloudinary.com/sports-master/image/upload/v1644649610/27ADF778-454B-4DB7-88B7-DC98202E2736_utb7xw.png",bannerUrl:"https://scontent.fmex34-1.fna.fbcdn.net/v/t1.6435-9/167022015_1317341031983063_7337313589197318410_n.jpg?_nc_cat=111&ccb=1-5&_nc_sid=a26aad&_nc_ohc=5ctqP2nFf7IAX94PNSO&_nc_ht=scontent.fmex34-1.fna&oh=00_AT_TzRHhhV73ji7wzW2X1u27TOU8TNlObwtp0ILc0DzC1Q&oe=62207F2C",id:"62075e5a13a43ace611fe5bd"}};
const responseClone = (typeof structuredClone === 'function')
&& structuredClone(responseData)
|| JSON.parse(JSON.stringify(responseData)); // fallback
const newData = {
title: 'tomoorow',
description: 'TEST',
date: 'Sunday, February 20th 2022',
category: 'NHL',
pickImageUrl: 'https://res.cloudinary.com/creaciones-inteligentes-roy/image/upload/v1644455039/Captura_de_Pantalla_2022-02-09_a_la_s_18.59.43_voy1pj.png',
};
insertDataItemAfterLastMatchingCondition(
responseClone.tipster.picks,
newData,
data => data.title === 'today',
);
console.log({ responseData, responseClone });
.as-console-wrapper { min-height: 100%!important; top: 0; }
CodePudding user response:
If you want to do it with spread operator (inmutable way), something like this should be enough:
const oldData = {
tipster: {
name: "Gallita FC",
description: "TEST",
picks: [
{
date: "Friday, February 18th 2022",
data: [
{
title: "yesterday",
description: "TEST",
date: "Friday, February 18th 2022",
category: "NHL",
pickImageUrl:
"https://res.cloudinary.com/creaciones-inteligentes-roy/image/upload/v1644455039/Captura_de_Pantalla_2022-02-09_a_la_s_18.59.43_voy1pj.png",
},
],
},
{
date: "Saturday, February 19th 2022",
data: [
{
title: "today",
description: "TEST",
date: "Saturday, February 19th 2022",
category: "NHL",
pickImageUrl:
"https://res.cloudinary.com/creaciones-inteligentes-roy/image/upload/v1644455039/Captura_de_Pantalla_2022-02-09_a_la_s_18.59.43_voy1pj.png",
},
],
},
],
imageUrl:
"https://res.cloudinary.com/sports-master/image/upload/v1644649610/27ADF778-454B-4DB7-88B7-DC98202E2736_utb7xw.png",
bannerUrl:
"https://scontent.fmex34-1.fna.fbcdn.net/v/t1.6435-9/167022015_1317341031983063_7337313589197318410_n.jpg?_nc_cat=111&ccb=1-5&_nc_sid=a26aad&_nc_ohc=5ctqP2nFf7IAX94PNSO&_nc_ht=scontent.fmex34-1.fna&oh=00_AT_TzRHhhV73ji7wzW2X1u27TOU8TNlObwtp0ILc0DzC1Q&oe=62207F2C",
id: "62075e5a13a43ace611fe5bd",
},
};
const newPick = {
title: "new title",
description: "new description",
date: "new date",
category: "new category",
pickImageUrl: "new image url",
};
const tipsterUpdate = {
...oldData,
tipster: {
picks: [...oldData.tipster.picks, newPick],
},
};
console.log(tipsterUpdate);
If you don't mind inmutability, just use push:
oldData.tipster.picks.push(newPick);