Esta es mi primera publicación, ¡así que intentaré hacer todo lo posible para ser lo más completo posible! Necesito convertir varios objetos de JavaScript que tienen el mismo valor en un solo objeto único con los totales de todas las demás claves en el objeto de cada uno.
Tengo una matriz que contiene objetos para diferentes escuelas y cada uno tiene un valor para la cantidad de estudiantes en la escuela. Esto es con lo que estoy trabajando:
let schools = [ { school: "a", students: 1000, }, { school: "b", students: 10000, }, { school: "b", students: 400, }, { school: "c", students: 10000, }, { school: "d", students: 2000, }, { school: "c", students: 1000, }, { school: "d", students: 4000, }, ]Quiero devolver una matriz de objetos individuales para cada escuela dada, con la suma de los valores de los estudiantes en cada uno de los objetos de las escuelas dadas. Aquí está el resultado que estoy esperando:
{ school: "a", students: 1000, }, { school: "b", students: 10400, }, { school: "c", students: 11000, }, { school: "d", students: 6000, } ]Así es como se ve mi solución hasta ahora:
let listOfUniqueSchools = []; for (let i = 0; i < schools.length; i++) { if (!listOfUniqueSchools.includes(schools[i].school)) { listOfUniqueSchools.push(schools[i].school); } else { } } let outputArray = []; for (let j = 0; j < listOfUniqueSchools.length; j++) { for (let k = 0; k < schools.length; k++) { let totalNumberOfStudents = 0; if (listOfUniqueSchools[j] == schools[k].school) { totalNumberOfStudents += schools[k].students; outputArray.push({ school: schools[k].school, students: totalNumberOfStudents, }); } } }Esto es lo que estoy recibiendo:
[ { school: "a", students: 1000, }, { school: "b", students: 10000, }, { school: "b", students: 400, }, { school: "c", students: 10000, }, { school: "c", students: 1000, }, { school: "d", students: 2000, }, { school: "d", students: 4000, }, ]Alguien sabe que tengo que cambiar para solucionar esto?
Esta solución usa un ciclo for (forEach) para llenar un nuevo objeto que tiene escuelas como claves y totales de estudiantes como valores. Luego usamos el método Object.keys para obtener una matriz de escuelas que se encuentran en el objeto de totales, y usamos la función de mapa para transformar los datos en el formato de salida esperado.
Es mucho más limpio que los bucles anidados.
const schools = [{ school: "a", students: 1000, }, { school: "b", students: 10000, }, { school: "b", students: 400, }, { school: "c", students: 10000, }, { school: "d", students: 2000, }, { school: "c", students: 1000, }, { school: "d", students: 4000, }, ] const totals = {} schools.forEach((entry) => { if (totals.hasOwnProperty(entry.school)) { totals[entry.school] += entry.students } else { totals[entry.school] = entry.students } }) const formattedTotals = Object.keys(totals).map((school) => ({ school: school, students: totals[school] })) console.log(formattedTotals)El problema en su código es que la parte Array.push está en el ciclo interno mientras que debería estar en el ciclo externo.
outputArray.push({ school: listOfUniqueSchools[j], students: totalNumberOfStudents, });Muévelo afuera, funcionará.
Podría ser más simple usando Array.reduce , vea el fragmento de código a continuación.
let schools = [ { school: "a", students: 1000, }, { school: "b", students: 10000, },{ school: "b", students: 400, }, { school: "c", students: 10000, }, { school: "d", students: 2000, }, { school: "c", students: 1000, }, { school: "d", students: 4000, },]; let listOfUniqueSchools = []; for (let i = 0; i < schools.length; i++) { if (!listOfUniqueSchools.includes(schools[i].school)) { listOfUniqueSchools.push(schools[i].school); } else { } } let outputArray = []; for (let j = 0; j < listOfUniqueSchools.length; j++) { let totalNumberOfStudents = 0; for (let k = 0; k < schools.length; k++) { if (listOfUniqueSchools[j] == schools[k].school) { totalNumberOfStudents += schools[k].students; } } outputArray.push({ school: listOfUniqueSchools[j], students: totalNumberOfStudents, }); } console.log(outputArray); // or simply use array reduce const result = schools.reduce((acc, item) => { const sum = acc.find(sum => sum.school === item.school); sum ? sum.students += item.students : acc.push({school: item.school, students: item.students}); return acc; }, []); console.log(result);Recorrería las escuelas y crearía un objeto donde las claves son escuelas ("a", "b", "c", etc.) y los valores son el número acumulativo de estudiantes.
Luego recorra esa matriz para crear una matriz de objetos, cada uno de los cuales tiene una "escuela" clave y un valor, y una clave "estudiantes" con el valor acumulativo.
let schools = [ { school: "a", students: 1000, }, { school: "b", students: 10000, }, { school: "b", students: 400, }, { school: "c", students: 10000, }, { school: "d", students: 2000, }, { school: "c", students: 1000, }, { school: "d", students: 4000, }, ] let totals = {} // Interim totals schools.forEach( function(school) { // console.log(school.students, school.school) totals[school.school] = ( totals[school.school] ?? 0 ) + school.students; }) let results = [] // Final results for ( const school in totals ) { results.push( { school: school, students: totals[school] } ) } console.log(results) /* Array(4) [ {…}, {…}, {…}, {…} ] 0: Object { school: "a", students: 1000 } 1: Object { school: "b", students: 10400 } 2: Object { school: "c", students: 11000 } 3: Object { school: "d", students: 6000 } length: 4 */