Tengo una estructura de datos de una matriz de objetos con la cantidad de horas dedicadas a varios roles diferentes, como a continuación:
[{"week 01" : {"Developer" : 1}}, {"week 01" : {"Project Manager" : 5}}, {"week 01" : {"Project Manager" : 6}}, {"week 01": {"Developer" : 8}}, {"week 02" : {"Strategy" : 4}}]Los roles y las semanas son dinámicos (es decir, no conozco los valores/clave de antemano) y me gustaría sumar todas las horas para el mismo rol y la misma semana para obtener el siguiente resultado:
[{"week 01" : { "Developer" : 9 "Project Manager" : 11 } }, {"week 02" : { "Strategy" : 4 } }] He intentado usar la función de reduce , pero parece que no puedo hacerlo bien:
function reduceArray(arr) { const result = arr.reduce((result, item) => { let obj = {}; const existing = result.find(function (x) { for (var prop in x) { if (x[prop] === item[prop]) { //same week number found //loop through roles for (var subProp in x[prop]) { if (x[prop][subProp] === item[prop][subProp]) { obj[prop][subProp] += x[prop][subProp] + item[prop][subProp] //This is where I lose myself in the prop-loops.... } } } } }) }, []) return result; } const data = [ { "week 01": { Developer: 1 } }, { "week 01": { "Project Manager": 5 } }, { "week 01": { "Project Manager": 6 } }, { "week 01": { Developer: 8 } }, { "week 02": { Strategy: 4 } }, ]; const result = data.reduce( (prev, item) => { for (const week in item) { if (prev[week]) { for (const act in item[week]) { if (prev[week][act]) { prev[week][act] += item[week][act]; } else { prev[week][act] = item[week][act]; } } } else { prev[week] = item[week]; } } return prev; }, {} ); console.log(result);Podría generar un solo objeto con los valores acumulados para todos los tipos.
const data = [{ "week 01": { Developer: 1 } }, { "week 01": { "Project Manager": 5 } }, { "week 01": { "Project Manager" : 6 } }, { "week 01": { Developer : 8 } }, { "week 02": { Strategy: 4 } }], result = data.reduce((r, o) => { Object .entries(o) .forEach(([week, q]) => Object .entries(q) .forEach(([type, value]) => { (r[week] ??= {})[type] ??= 0; r[week][type] += value; }) ); return r; }, {}); console.log(result); .as-console-wrapper { max-height: 100% !important; top: 0; }Aquí hay una manera simple de hacerlo. Esperemos que los comentarios sean útiles.
const data = [ { "week 01": { Developer: 1 } }, { "week 01": { "Project Manager": 5 } }, { "week 01": { "Project Manager": 6 } }, { "week 01": { Developer: 8 } }, { "week 02": { Strategy: 4 } } ]; function cleanUp(data) { return data.reduce((acc, item) => { // assign variables const week = Object.keys(item).pop(); const [job, value] = Object.entries(item[week]).pop(); // initialise them, if they aren't in the accumilator. if (!acc[week]) acc[week] = {}; if (!acc[week][job]) acc[week][job] = 0; // add the value acc[week][job] += value; return acc; }, {}); } console.log(cleanUp(data)); Aquí hay uno que usa for...in lugar de Object.keys() y Object.entries() ,
const data = [ { "week 01": { Developer: 1 } }, { "week 01": { "Project Manager": 5 } }, { "week 01": { "Project Manager": 6 } }, { "week 01": { Developer: 8 } }, { "week 02": { Strategy: 4 } } ]; function cleanUp(data) { return data.reduce((acc, item) => { for (const week in item) { if (!acc[week]) acc[week] = {}; for (const job in item[week]) { if (!acc[week][job]) acc[week][job] = 0; acc[week][job] += item[week][job]; } } return acc; }, {}); } console.log(cleanUp(data));