Estoy tratando de deduplicar una matriz de objetos JSON donde el contenido y el autor son los mismos, pero la marca de tiempo es ligeramente diferente (es decir, dentro de 1 segundo). Me gustaría conservar los mensajes duplicados como un campo nuevo, llamado duplicados. Por ejemplo, considere lo siguiente que tiene como entradas 2,3 y 5 mensajes que deben ser deduplicados:
myObject = [ {content: 'content1', date: '1980-08-01 12:12:40.000', author: 'Person1'}, {content: 'content2', date: '1980-08-01 12:12:40.900', author: 'Person2'}, {content: 'content2', date: '1980-08-01 12:12:41.100', author: 'Person2'}, {content: 'content3', date: '1980-08-01 12:12:41.000', author: 'Person1'}, {content: 'content2', date: '1980-08-01 12:12:41.400', author: 'Person2'}, {content: 'content4', date: '1980-08-01 12:12:45.100', author: 'Person2'}, ]debe transformarse en:
deduped = [ {content: 'content1', date: '1980-08-01 12:12:40.000', author: 'Person1', duplicates: 0}, {content: 'content2', date: '1980-08-01 12:12:40.900', author: 'Person2', duplicates: 2}, {content: 'content3', date: '1980-08-01 12:12:41.000', author: 'Person1', duplicates: 0}, {content: 'content4', date: '1980-08-01 12:12:45.100', author: 'Person2', duplicates: 0}, ]La parte con la que tengo problemas es la fecha y hora. Ordenar por fecha y hora y luego reducir es propenso a errores si aparece un mensaje no duplicado entre los duplicados. Y comparar el valor de cadena de las fechas y horas también es propenso a errores porque dos mensajes pueden estar muy juntos, pero se muestran con 1 segundo de diferencia en función de dónde caen.
Usando lodash _.uniqWith, puedo deduplicar en base a la combinación de un timedelta real con contenido y autor idénticos, pero me falta el campo de duplicados...
const dedupedButNoCount = _.uniqWith(myObject, (item1, item2) => {return (item1.content== item2.content) && (item1.author== item2.author) && ((new Date(item1.date).getTime() - new Date(item2.date).getTime())<500)} )¿Algún consejo sobre cómo deduplicar una matriz de objetos con fechas y horas similares pero no idénticas?
Yo he hecho eso, pero uso una clasificación...
const getTimeMs = YMDhmsx => // date string conversion to UTC (time zone = 0) { let [Y,M,D,h,m,s,x] = YMDhmsx.split(/\-|\.|\s|\:/).map(Number) return (new Date(Date.UTC(Y,--M,D,h,m,s,x))).getTime() // time UTC value in ms } , myObject = [ {content: 'content1', date: '1980-08-01 12:12:40.000', author: 'Person1'}, {content: 'content2', date: '1980-08-01 12:12:40.900', author: 'Person2'}, {content: 'content2', date: '1980-08-01 12:12:41.100', author: 'Person2'}, {content: 'content3', date: '1980-08-01 12:12:41.000', author: 'Person1'}, {content: 'content2', date: '1980-08-01 12:12:41.400', author: 'Person2'}, {content: 'content4', date: '1980-08-01 12:12:45.100', author: 'Person2'}, ] let result = myObject .sort( (a,b) => a.content.localeCompare(b.content) || a.author.localeCompare(b.author) || a.date.localeCompare(b.date) ) .reduce( (r,el,i,{[i-1]:prev}) => { let msTime = getTimeMs(el.date) if (el.content === prev?.content && el.author === prev?.author && (msTime - r.msTime) <= 1000 ) // 1 second less on previous r.current.duplicates++; else { r.current = {...el, duplicates:0 } r.result.push( r.current ) } r.msTime = msTime return r } , {msTime:0, current:null, result:[] }) .result; console.log ( 'result:\n' + JSON.stringify( result ).replaceAll('},{','}\n,{') ) .as-console-wrapper {max-height: 100% !important;top: 0;} .as-console-row::after {display: none !important;}