Tengo un objeto de matriz de javascript de una entrada de base de datos como esta:
[{ date: '2021-09-15', type: 'cats', value: 4 }, { date: '2021-09-15', type: 'dogs', value: 5 }, { date: '2021-09-16', type: 'cats', value: 1 }, { date: '2021-09-16', type: 'dogs', value: 4 }]Y necesito una salida como esta:
[{ date: '2021-09-15', cats: 4, dogs: 5 }, { date: '2021-09-16', cats: 1, dogs: 4 }]Estoy tratando de usar la función de reducción de esta manera, sin embargo, no puedo hacer que funcione (está agrupando los datos pero no modificándolos, por lo que quedan con un solo valor)
const data = [ { date: '2021-09-15', type: 'cats', value: 4 }, { date: '2021-09-15', type: 'dogs', value: 5 }, { date: '2021-09-16', type: 'cats', value: 1 }, { date: '2021-09-16', type: 'dogs', value: 4 } ] const groups = data.reduce((groups, item) => { const key = item[item.date]; if (!groups[key]) { groups[item.date] = [] } if (item.type == "cats") { item.cats = item.value; } else if (item.type == "dogs") { item.dogs = item.value; } groups[item.date].push(item); return groups; }, {}); console.log(groups) .as-console-wrapper { max-height: 100% !important; }Si segundo objeto con la misma date y type ya existente. Esto también cubre el caso en el que tiene varios objetos con el mismo type , luego sumará el value
const arr = [ { date: "2021-09-15", type: "cats", value: 4 }, { date: "2021-09-15", type: "cats", value: 5 }, { date: "2021-09-16", type: "cats", value: 1 }, { date: "2021-09-16", type: "dogs", value: 4 }, ]; const map = new Map(); arr.forEach((o) => { const { date, type, value } = o; if (!map.has(date)) map.set(o.date, { date, [type]: value }); else { const target = map.get(date); const { type: newType, value: newValue } = o; target[newType] = target[newType] ? target[newType] + newValue : newValue; } }); const result = [...map.values()]; console.log(result); /* This is not a part of answer. It is just to give the output fill height. So IGNORE IT */ .as-console-wrapper { max-height: 100% !important; top: 0; }Este es realmente un proceso de dos pasos...
date en un mapa const data = [{"date":"2021-09-15","type":"cats","value":4},{"date":"2021-09-15","type":"dogs","value":5},{"date":"2021-09-16","type":"cats","value":1},{"date":"2021-09-16","type":"dogs","value":4}] const t1 = performance.now() const mapped = data.reduce((map, { date, type, value }) => { // get the current entry for date, default to `{}` const obj = map.get(date) ?? {} // merge and set the new entry return map.set(date, { ...obj, [ type ]: (obj[type] ?? 0) + value }) }, new Map()) const groups = Array.from(mapped, ([ date, obj ]) => ({ date, ...obj })) const t2 = performance.now() console.log(groups, `\nTook ${t2 - t1}ms`) .as-console-wrapper { max-height: 100% !important; }No quedó claro a partir de su pregunta, pero esta respuesta resume los valores del mismo tipo para la misma fecha.