tengo los siguientes objetos
Person { name: string birthday: Date lifeEvents: LifeEvent[] } LifeEvent { eventId: number message: string comments: string } Como los datos vienen en fragmentos, tendré una matriz de Person con un objeto que tiene name y birthday con valores pero lifeEvents está vacío (Piense en este como un objeto principal).
Todos los demás objetos no tendrán la fecha de nacimiento ni el nombre y solo tendrán un LifeEvent con eventId y message con valores o eventId y comments .
Dentro de esa matriz, necesito obtener el objeto principal, que tiene nombre y cumpleaños con valores, luego obtener todos los eventos de vida de los objetos restantes, fusionar todos los elementos que contienen el mismo ID de evento en un LifeEvent y luego enviarlo a los eventos de vida del padre.
Probé array.reduce, array.map pero no puedo encontrar una forma de combinar esos objetos en uno.
Mi salida debe ser solo una Person con todos los eventos de eventId fusionados por lifeEvents
Data de muestra:
let results = [ { name: 'Test1', birthday: '2022-06-14', lifeEvents: null }, { name: null, birthday: null, lifeEvents: [ { eventId: 1, message: 'First event', comments: null } ] }, { name: null, birthday: null, lifeEvents: [ { eventId: 2, message: 'Second event', comments: null } ] }, { name: null birthday: null lifeEvents: [ { eventId: 1, message: null, comments: 'First event comment' } ] }, { name: null birthday: null lifeEvents: [ { eventId: 2, message: null, comments: 'Second event comment' } ] }, ]Agradezco cualquier ayuda.
Lo siguiente produce el resultado solicitado basado en los ejemplos proporcionados:
let results = [ { name: 'Test1', birthday: '2022-06-14', lifeEvents: null }, { name: null, birthday: null, lifeEvents: [ { eventId: 1, message: 'First event', comments: null } ] }, { name: null, birthday: null, lifeEvents: [ { eventId: 2, message: 'Second event', comments: null } ] }, { name: null, birthday: null, lifeEvents: [ { eventId: 1, message: null, comments: 'First event comment' } ] }, { name: null, birthday: null, lifeEvents: [ { eventId: 2, message: null, comments: 'Second event comment' } ] }, ]; // extract parent const parentResult = results.find((result) => result.name); // generate unique events from sibling entities const uniqueEvents = new Map(); results.forEach((result) => result.lifeEvents?.forEach( (lifeEvent) => { if (uniqueEvents.has(lifeEvent.eventId)) { updateEvent(lifeEvent); } else { uniqueEvents.set(lifeEvent.eventId, { eventId: lifeEvent.eventId, message: lifeEvent.message, comments: lifeEvent.comments}); } }) ); // function to update event that is already stored in uniqueEvents function updateEvent(lifeEvent) { const existingLifeEvent = uniqueEvents.get(lifeEvent.eventId); if (lifeEvent.message) existingLifeEvent.message = lifeEvent.message; if (lifeEvent.comments) { if (existingLifeEvent.comments) { existingLifeEvent.comments.concat(lifeEvent.comments) } else { existingLifeEvent.comments = lifeEvent.comments; } } } // populate lifeEvents inside the parentResult parentResult.lifeEvents = []; uniqueEvents.forEach((uniqueId) => { parentResult.lifeEvents.push(uniqueId); }); console.log(parentResult);Premisa: la estructura de datos que está utilizando es incorrecta, debe intentar usar matrices con modelos homogéneos.
Dicho esto, utilicé un método de reducción, con la condición de tratar el primer elemento de manera diferente a los demás.
Lo último, dijiste fusionar eventos de vida, supongo que querías sobrescribir los valores nulos para eventos con los mismos identificadores, si quieres sobrescribir todos los valores, entonces puedes omitir la función de utilidad de fusión que escribí.
let results = [{ name: 'Test1', birthday: '2022-06-14', lifeEvents: null, }, { name: null, birthday: null, lifeEvents: [{ eventId: 1, message: 'First event', comments: null, }, ], }, { name: null, birthday: null, lifeEvents: [{ eventId: 2, message: 'Second event', comments: null, }, ], }, { name: null, birthday: null, lifeEvents: [{ eventId: 1, message: null, comments: 'First event comment', }, ], }, { name: null, birthday: null, lifeEvents: [{ eventId: 2, message: null, comments: 'Second event comment', }, ], }, ]; const merge = (o1, o2) => { const r = {...o1} Object.keys(o1).forEach(k => r[k] = o2[k] || o1[k]) return r } const r = results.reduce((o, curr, i) => { if (i === 0) { return { ...o, lifeEvents: [] }; } else { const currentEvent = curr.lifeEvents[0] const idx = o.lifeEvents.findIndex((_o) => _o.eventId === currentEvent.eventId); if (idx !== -1) return { ...o, lifeEvents: o.lifeEvents.map((_o, i) => i === idx ? merge(_o, currentEvent) : _o) } else return { ...o, lifeEvents: [...o.lifeEvents, currentEvent] } } }, results[0]); console.log("RESULT:", r);