Estoy luchando por recuperar un subconjunto de una matriz de objetos en función de condiciones específicas. Tengo una matriz de objetos en el siguiente formato:
const messages = [ { summary: '[x1fg66pwq-qft] Second reminder to submit supporting documents', date: '1624652200', type: 1 }, { summary: '[x1fg66pwq-fgh] Final reminder to submit supporting documents', date: '1629058600', type: 4 }, { summary: '[zy9l89ptb-yuw] Please submit your proof of address', date: '1631708200', type: 2 }, { summary: '[ggk9nygh8-pmn] Your application has been successful.', date: '1634300200', type: 1 }, ]Hay otra matriz que proporciona los mensajes para recuperar en función de la identificación del mensaje entre corchetes del resumen:
const messageIds = ['x1fg66pwq', 'zy9l89ptb'];
El resultado debería ser la recuperación de los mensajes más recientes en función de lo que hay en la matriz messageIds . El campo de fecha está en época.
const result = [ { summary: '[x1fg66pwq] Final reminder to submit supporting documents', date: '1629058600', type: 4 }, { summary: '[zy9l89ptb] Please submit your proof of address', date: '1631708200', type: 2 }, ]Para lograr lo anterior, intenté combinar un filtro y encontré cuál no me funcionó:
const result = messages.filter((message) => messageIds.find(id => message.summary.includes(testEvent)) );Esperaría que lo anterior devuelva el primer resultado en la matriz que tiene el resumen especificado. Sin embargo, esto siempre me devuelve la matriz completa sin filtrar. ¿Podría alguien por favor ayudarme a lograr esto?
Creo que solo necesita agregar una sort al final si entiendo su pregunta correctamente
.sort((b,a) => +a.date - +b.date)
const messages = [{ summary: '[x1fg66pwq-qft] Second reminder to submit supporting documents', date: '1624652200', type: 1 }, { summary: '[x1fg66pwq-fgh] Final reminder to submit supporting documents', date: '1629058600', type: 4 }, { summary: '[zy9l89ptb-yuw] Please submit your proof of address', date: '1631708200', type: 2 }, { summary: '[ggk9nygh8-pmn] Your application has been successful.', date: '1634300200', type: 1 }, ] const messageIds = ['x1fg66pwq', 'zy9l89ptb']; const result = messages.filter((message) => messageIds.some(id => message.summary.includes(id)) ).sort((b, a) => +a.date - +b.date); console.log(result)Mientras busca el último , primero puede crear un mapa o un objeto simple, codificado por los ID de mensajes de destino, y luego asignar a cada mensaje el valor más grande para su propiedad de date :
const messages = [{summary: '[x1fg66pwq-qft] Second reminder to submit supporting documents',date: '1624652200',type: 1},{ summary: '[x1fg66pwq-fgh] Final reminder to submit supporting documents',date: '1629058600', type: 4},{ summary: '[zy9l89ptb-yuw] Please submit your proof of address',date: '1631708200',type: 2},{ summary: '[ggk9nygh8-pmn] Your application has been successful.', date: '1634300200',type: 1},]; const messageIds = ['x1fg66pwq', 'zy9l89ptb']; // Create object keyed by the message ids: let obj = Object.fromEntries(messageIds.map(id => [id, null])); // Link the message to each id with minimal date for (let msg of messages) { let id = msg.summary.match(/^\[(.*?)-/)?.[1]; if (obj[id] === null || +msg.date > +obj[id]?.date) obj[id] = msg; } let result = Object.values(obj); console.log(result);Las piezas de esto son bastante fáciles. Solo es cuestión de unirlos:
const matches = (messages, ids) => ids .flatMap ( id => messages .filter (({summary}) => summary .startsWith ('[' + id)) .sort (({date: a}, {date: b}) => b - a) .slice (0, 1) ) const messages = [{summary: '[x1fg66pwq-qft] Second reminder to submit supporting documents', date: '1624652200', type: 1}, {summary: '[x1fg66pwq-fgh] Final reminder to submit supporting documents', date: '1629058600', type: 4}, {summary: '[zy9l89ptb-yuw] Please submit your proof of address', date: '1631708200', type: 2}, {summary: '[ggk9nygh8-pmn] Your application has been successful.', date: '1634300200', type: 1}] const messageIds = ['x1fg66pwq', 'zy9l89ptb'] console .log (matches (messages, messageIds)) Esta versión simplemente ignorará las identificaciones que no coincidan. Eso puede o no ser lo que quieres. También hace algo que sería estúpido si tuviera que buscar una gran cantidad de datos para cada id: encuentra el máximo ordenándolos y eligiendo el primero. Para datos pequeños está bien. Para datos más grandes (cientos de miles o millones es probablemente donde primero podría haber un problema), esto es O (n log (n)) , que es más lento que la siguiente técnica, que es O (n) :
const maxBy = (fn) => (xs) => xs .reduce ( ({curr, max}, x) => fn(x) > max ? {curr: x, max: fn (x)} : {curr, max}, {curr: null, max: -Infinity} ) .curr const matches = (messages, ids) => ids .flatMap ( id => maxBy (({date}) => Number(date)) (messages .filter (({summary}) => summary .startsWith ('[' + id))) ) const messages = [{summary: '[x1fg66pwq-qft] Second reminder to submit supporting documents', date: '1624652200', type: 1}, {summary: '[x1fg66pwq-fgh] Final reminder to submit supporting documents', date: '1629058600', type: 4}, {summary: '[zy9l89ptb-yuw] Please submit your proof of address', date: '1631708200', type: 2}, {summary: '[ggk9nygh8-pmn] Your application has been successful.', date: '1634300200', type: 1}] const messageIds = ['x1fg66pwq', 'zy9l89ptb'] console .log (matches (messages, messageIds)) Esto usa una función maxBy que itera a través de la lista para encontrar el máximo de acuerdo con la función proporcionada, devolviendo null para una matriz vacía.
Esta versión incluirá null en la salida en caso de que no se encuentre la identificación. Este podría ser el comportamiento preferido, pero si no, puede ajustarlo para filtrar la salida en busca de valores no nulos.
Obviamente, en cualquiera de estas soluciones, podría reemplazar summary .startsWith ('[' + id) con summary .includes (id) , que es más flexible, pero quizás menos exacto.