Tengo registros de archivos json que son objetos que parecen
{ "logs": [ { "id": "12321321321321", "email": "test@email.com", "message": "ahahaha" }, { "id": "12321321312", "email": "test@email.com", "message": "hahahaha." }, "id": "12321321321" }Necesito devolver un nuevo objeto que contenga
{ "hello_id": outer id of the json file, "array": [ { "email": "test@me.com", "total": 2 } ] }Hasta ahora estoy recorriendo los archivos json y tengo
jsonsInDirectory.forEach((file) => { const fileData = fs.readFileSync(path.join("./logs", file), "utf8"); const jsonData = JSON.parse(fileData); } });La clave es "logs" e "id" y los valores son los objetos en los "logs" y el valor de "id"
¿Cómo puedo contar y devolver un nuevo objeto al mismo tiempo?
Puede probar este enfoque: cree un objeto hash que cuente los correos electrónicos. Luego, simplemente mapéelo en una matriz de objetos.
const data = { logs: [{ id: "89004ef9-e825-4547-a83a-c9e9429e8f95", email: "noah.sanchez@me.com", message: "successfully handled skipped operation." }, { id: "89004ef9-e825-4547-a83a-c9e9429e8f95", email: "noah.sanchez@me.com", message: "successfully handled skipped operation." }, { id: "89004ef9-e825-4547-a83a-c9e9429e8f95", email: "noname@me.com", message: "successfully handled skipped operation." }], id: "56f83bed-3705-4115-9067-73930cbecbc0", }; const emails = data.logs.reduce((acc, { email }) => { acc[email] = (acc[email] ?? 0) + 1; return acc; }, {}); const tally = Object.entries(emails) .map(([email, total]) => ({ email, total })); const result = { logs_id: data.id, tally }; console.log(result) .as-console-wrapper { max-height: 100% !important; top: 0 }Cuando haces const jsonData = JSON.parse(fileData); , obtiene los datos del archivo como JSON y, conociendo la estructura de ese JSON, puede obtener fácilmente la información.
He creado un ejemplo https://codesandbox.io/s/stackoverflow-logs-count-example-jys2vg?file=/src/index.js
Puede que no resuelva exactamente lo que quieres.
Para resolver este problema con la mayor eficiencia de tiempo, puede crear un objeto de conteo creando primero un mapa de las ocurrencias de cada correo con el correo electrónico como clave y el número de ocurrencias como valor, ya que esto tomará constante (O(1 )) tiempo de ejecución, después de lo cual puede crear la matriz de conteo del mapa como se indica a continuación
output = [] jsonsInDirectory.forEach((file) => { const fileData = fs.readFileSync(path.join("./logs", file), "utf8"); const jsonData = JSON.parse(fileData); var map = {} jsonData.logs.forEach((log) => { if(log.email in map){ map[log.email] += 1 } else { map[log.email] = 1 } }); var tally = [] for(var email in map){ tally.push({email: email, total: map[email]}) } output.push({logs_id: jsonData['id'], tally: tally}); })