Playground - Obten el promedio de los estudiantes
Clase 19 de 99 • 30 días de JavaScript
Contenido del curso
Clase 19 de 99 • 30 días de JavaScript
Contenido del curso
Leonardo de los angeles Espinoza Hernandez
Fernando García Guerrero
Isabelle de Souza
Ramiro Vazquez
Francisco Ponce
Rahiber Paradas
Santiago Quintero
Orangel Brito
Francisco Jesús Eslava Fernández
Raul Ernesto Castillejos Jimenez
Santiago Palacio Vásquez
Leonardo de los angeles Espinoza Hernandez
Hiver Tapia
Cristian Romero
Cristian Romero
Javier Hernandez
Esteban Castaño
jorge vilchis
Sergio Luis Arango Montes
Leonardo de los angeles Espinoza Hernandez
Nicolás Plaza
Leonardo de los angeles Espinoza Hernandez
Esteban Alzate Atehortua
Esteban Alzate Atehortua
Carlos Leandro Miguel Latyn
Leonardo de los angeles Espinoza Hernandez
Carlos Leandro Miguel Latyn
Cesar Francisco Zendejas Torres
Andrés Soret Chacin
Sebastian David Exeni Cazón
EDGAR PINTO
EDGAR PINTO
🛡️Escudo anti spoilers🛡️
. A este punto espero ya entiendas cual es el propósito de este texto, y si no, igual lo pongo para hacer espacio en este comentario (no olvides darle like). . Este es un comentario para aquellos y aquellas estudiantes que sea su primera vez resolviendo este coding playground y evites auto spoilearte viendo las soluciones de la comunidad (por favor SIGAN compartiendo sus soluciones, nos fascina ver como lo hacen). A su vez, este comentario tendrá la explicación a este problema más abajo, abajo del gif random que siempre suelo poner por lo que ya sabes que esperar si haces más scroll . Momento random del día !dog .
Explicación
En este caso, no optamos por usar bucles. En su lugar fueron métodos propios de los arrays (para variar con las soluciones pero facilmente puede hacerse con un for o un while, for of, etc...)
export function getStudentAverage(students) { // Creamos un array donde obtendremos los estudiantes con su promedio const studentsWithAverage = students.map((student) => { // separamos las notas en una sola variable para hacerlo más legible const grades = student.grades; // calculamos el promedio sumando todas las notas para dividirlas // en el total de materias const average = grades.reduce((total, item) => total + item, 0) / grades.length; return { // Retornamos un objeto con el nombre del estudiante name: student.name, // Junto con su promedio a 2 decimales // Es importante parsearlo con Number porque el método toFixed devuelve un string average: Number(average.toFixed(2)), }; }); // Después pasamos a hacer lo mismo pero obteniendo el promedio de la clase const classAverage = studentsWithAverage.reduce((total, student) => total + student.average, 0) / studentsWithAverage.length; // Sumamos todos los promedios y los dividimos entre el total de estudiantes // Al final armamos un objeto que será el que retornaremos const rta = { // De igual manera pasamos el promedio de la clase a 2 decimales classAverage: Number(classAverage.toFixed(2)), students: studentsWithAverage, }; // Y retornamos el objeto anterior return rta; }
Y ¡listo! . Si llegaste a esta parte de la lectura te comparto un fun fact, esta solución fue propuesta por el gran Nicobytes, mi solución era otra pero esta se ve más coqueta. . No olvides dejar tu corazoncito
Gente aquí vengo yo a que no vean las respuestas de los demás + + + + + + + + + + +
Más limpio Escudo anti spoilers
export function getStudentAverage(students) { // Tu código aquí 👈 let total = 0; const course = { classAverage: 0, students: [] }; for (const student of students) { let sum = student.grades.reduce((sum, grade) => sum + grade); let averageStudent = (sum / student.grades.length).toFixed(2); const aStudent = { name: student.name, average: Number(averageStudent) } course.students.push(aStudent); total += Number(averageStudent); } course.classAverage = Number((total / students.length).toFixed(2)); return course; }
Por favor no más loops dentro de loops, me estoy lastimando :(
export function getStudentAverage(students) { // Tu código aquí 👈 const studensAverageGrades = students.map(({ name, grades }) => ({ name: name, average: +((grades.reduce((acc, cur) => acc += cur, 0) / grades.length).toFixed(2)) })) return { classAverage: +(studensAverageGrades.reduce((acc, cur) => acc += cur.average,0)/studensAverageGrades.length).toFixed(2), students: studensAverageGrades } }
que interesante tu solucion
Genial.
Aquí mi solución:
export function getStudentAverage(students) { const final = { classAverage: 0, students: [] }; const arrayPromedioFinal = []; let promedioFinal; for (let objeto of students) { const promedio = objeto["grades"].reduce((a, b) => a + b); arrayPromedioFinal.push(Number((promedio / objeto["grades"].length).toFixed(2))); promedioFinal = arrayPromedioFinal.reduce((a, b) => a + b) / students.length; final.classAverage = Number(promedioFinal.toFixed(2)); final.students.push( { name: objeto.name, average: Number((promedio / objeto["grades"].length).toFixed(2)), }, ); }; return final; }
Hey dude, aqui mi solución :
function getStudentAverage(students) { //Primero, creamos una variable totalAverage que utilizaremos para acumular los promedios individuales de cada estudiante let totalAverage = 0; //Luego, iteramos a través del array de estudiantes usando el método map() y calculamos el promedio de cada estudiante usando el método reduce(). const studentAverages = students.map(student => { const average = student.grades.reduce((sum, grade) => sum + grade, 0) / student.grades.length; //Dentro del map(), también agregamos el promedio del estudiante a la variable totalAverage y redondeamos el promedio a dos decimales usando el método toFixed(). totalAverage += average; return { name: student.name, average: Number(average.toFixed(2)) }; }); //Después de calcular los promedios individuales de cada estudiante, calculamos el promedio de la clase dividiendo totalAverage por la cantidad de estudiantes y redondeando el resultado a dos decimales. const classAverage = Number((totalAverage / students.length).toFixed(2)); //Creamos el objeto de salida con los valores correspondientes y lo retornamos. return { classAverage: Number(classAverage), students: studentAverages }; }
Muy buena solucion!
Gracias por. compartir
gracias por los comentarios
La siguiente función genera un error en este entorno de ejecución de pruebas, sin embargo… funciona si lo pruebas en tu terminal con Node.js, o directamente en la consola de tu navegador.
/** * Proccess the data to get the average of the class and the average of each student. * * @param {Array<Object>} students - Array of objects with name and grades properties. * @returns {Object} Object with classAverage and students with name and average properties. */ function getStudentAverage(students) { let classAverage = 0 for (const student of students) { const grades = student.grades let average = grades.reduce((a, b) => a + b) / grades.length average = +average.toFixed(2) delete student.grades student.average = average classAverage += average } classAverage = +(classAverage / students.length).toFixed(2) return { classAverage, students } }
Identificación del problema:
Logré identificar que el problema solo sucede cuando uso la palabra clave delete para borrar la propiedad grades del objeto student. En este caso consideré mejor utilizar delete, en vez de desestructuración, ya que en este caso no consideré necesario crear un nuevo array de objetos student, ya que no requiero eliminar muchas propiedades del mismo, en realidad solo requiero eliminar una propiedad de los objetos student contenidos en el array students, por lo que tampoco consideré necesario aplicar un map, y retornar un nuevo array de nuevos objetos con las propiedades que requiero, por cada objeto del array.
Contextualización (delete vs desestructuración):
const obj = { prop1: 'Valor 1', prop2: 'Valor 2', prop3: 'Valor 3' } // Ejemplo de eliminación de propiedad con delete delete obj.prop2 console.log(obj); // { prop1: 'Valor 1', prop3: 'Valor 3' } // Ejemplo de desestructuración de objeto const { prop2, ...rest } = obj console.log(prop2); // 'Valor 2' console.log(rest); // { prop1: 'Valor 1', prop3: 'Valor 3' }
Solución:
Aunque no era mi intención resolverlo de esta manera, esta fue la mejor solución alternativa que se me ocurrio para que funcionara en el entorno de ejecución de pruebas de platzi:
function getStudentAverage2(students) { let classAverage = 0 students = students.map(student => { const grades = student.grades let average = grades.reduce((a, b) => a + b) / grades.length average = +average.toFixed(2) student.average = average classAverage += average return { name: student.name, average } }) classAverage = +(classAverage / students.length).toFixed(2) return { classAverage, students } }
Si bien algunos de mis propósitos aquí son mejorar y seguir aprendiendo, y entiendo que hay diversas soluciones alternativas y algunas serán más adecuadas para este caso que otras, no me siento conforme :( ya que no entiendo porque la primera solución que se me ocurrió, no funciona aquí... Ya que si comparo los resultados que arrojan ambas soluciones que propuse, son exactamente iguales :/
const result1 = getStudentAverage(students) const result2 = getStudentAverage2(students) console.log(JSON.stringify(result1) === JSON.stringify(result2)) //true
Y se preguntarán entonces: por qué esto es una pregunta y no un aporte. Bueno... si bien existen alternativas a
delete, el hecho de que no se pueda utilizar aquí, me genera dudas.
Suposición:
La palabra clave delete no está soportada en este entorno de ejecución de pruebas JS.
Dudas:
¿Por qué razón sucede esto, el hecho de que no se pueda usar delete, acaso tiene que ver con la seguridad del entorno de ejecución de pruebas y una restricción del mismo, o acaso es algo más, quizá algo que ni siquiera tenga que ver con delete?
¡Hola, Santiago!
/
Te tengo una buena y una mala noticia.
/
La buena es que delete si es soportado por el playground y tu solución está perfecta.
/
La mala, es que tu código lo que hace es modificar el array original mismo array que es usado para las siguientes pruebas y por eso te da un error de grades is undefined dentro del playground.
/
¿Por qué sucede esto?
Bueno para serte sincero, no pensamos que alguien usara mutable functions para los ejercicios básicos pero NO queremos limitarte a soluciones básicas. / De entrada te ofrezco una disculpa por esta mala experiencia y te agradezco por el feedback, ya mismo mande el fix para este ejercicio y tu solución funcione sin problema alguno (te avisaremos cuando esto pase). / Por ahora te ofrezco otro reto adicional, tu solución pasa sin ningún problema si haces un deep copy del array. Y así trabajas con una copia del input. / Mil gracias por tus comentarios, te ofrezco unirte al discord oficial de Platzi donde encontrarás un canal específico del reto donde podremos darte una pronta respuesta a este y distintos problemas que llegues a tener.
Un abrazo! 💪
Saludos comunidad platzi lo resolví de esta manera:
export function getStudentAverage(students) { let sumapromedios = 0; let promediados = students.map((student) => { const promedio = Number((student.grades.reduce((sum, value) => sum + value, 0) / student.grades.length).toFixed(2)); sumapromedios += promedio; return { name: student.name, average: promedio, }; }) const nuevalista = { classAverage: Number((sumapromedios / students.length).toFixed(2)), students: promediados }; return nuevalista; }
Esta fue mi solución:
export function getStudentAverage(students) { let allNotes = []; for (let value of students) { for (let grade of value.grades) { allNotes.push(grade); } } const classAverage = allNotes.length > 0 ? allNotes.reduce((acc, n) => acc + n, 0) / allNotes.length : 0; const studentsAverage = students.map(student => ({ name: student.name, average: student.grades.length > 0 ? Number((student.grades.reduce((acc, n) => acc + n, 0) / student.grades.length).toFixed(2)) : 0 })); return { classAverage: Number(classAverage.toFixed(2)), students: studentsAverage }; }
Despues de casi 3 horas de intento y error 🫠
Luego le dije a ChatGPT que lo resolviera, y fue mucho más óptimo:
export function getStudentAverage(students) { const studentsAverage = students.map(s => { const avg = s.grades.length ? s.grades.reduce((a, n) => a + n, 0) / s.grades.length : 0; return { name: s.name, average: Number(avg.toFixed(2)) }; }); const allGrades = students.flatMap(s => s.grades); const classAvg = allGrades.length ? allGrades.reduce((a, n) => a + n, 0) / allGrades.length : 0; return { classAverage: Number(classAvg.toFixed(2)), students: studentsAverage }; }
Es verdad que lo que yo hice primero fue buscar el promedio total de todos los estudiantes, esto porque no había entendido bien el output, luego entonces fui a sacar el promedio de cada estudiante.
ChatGPT lo que hizo primero fue sacar el promedio de cada estudiante, y luego usarlos para sacar el promedio total del promedio de cada estudiante. Así ahorro espacio en memorio, utilizo menos loops, y tal.
Mi forma de resolver el ejercicio
export function getStudentAverage(students) { let classAverage = 0; let studentAverage = []; for (let i = 0; i < students.length; i++){ const grades = students[i].grades; let average = grades.reduce(function (acumulador, grades) { return acumulador + grades; }) / grades.length; studentAverage.push({ name: students[i].name, average: +average.toFixed(2)}); classAverage += average; } classAverage = +(classAverage / students.length).toFixed(2); return { classAverage: classAverage, students: studentAverage }; }
Esta es mi solución
export function getStudentAverage(studentsArray) { const students = studentsArray.map(student => { return { name: student.name, average: +(student.grades.reduce((acc, sum) => acc + sum, 0) / student.grades.length).toFixed(2) } }); const classAverage = +(students.reduce((acc, sum) => acc + sum.average, 0) / studentsArray.length).toFixed(2); return { classAverage, students } }
aqui mi aporte
export function getStudentAverage(students) {
let totalClassSum = 0;
let totalGradesCount = 0;
const studentsWithAverage = students.map(student => {
const sum = student.grades.reduce((acc, grade) => acc + grade, 0);
const average = parseFloat((sum / student.grades.length).toFixed(2));
totalClassSum += sum;
totalGradesCount += student.grades.length;
return {
name: student.name,
average: average
};
});
const classAverage = parseFloat((totalClassSum / totalGradesCount).toFixed(2));
return {
classAverage: classAverage,
students: studentsWithAverage
};
}
No se por que pero en el playground no me funciona esta solucion mientras que en Node si esta funcionando. Alguien tiene idea de que pasa?
function getStudentAverage(arr) { let output = {}; const students = []; classAverage = 0; for(element of arr){ const student = {}; student.name = element.name; student.average = parseFloat( ((element.grades.map(x => x/element.grades.length)) .reduce((sum, num) => sum + num,0)) .toFixed(2) ); students.push(student); } for(student of students){ classAverage += student.average; } output.classAverage = parseFloat( (classAverage/students.length) .toFixed(2) ); output.students = students; return output; }
¡Hola @Sergio_A!
¡Tu solución está perfecta! El problema por el cual las pruebas no pasan es porque estás omitiendo el declarar algunas variables como la de los ciclos for... of o la variable como classAverage
Simplemente agrega let o const dependiendo el caso y funcionará a la primera 🙌
Un saludo!
Buenas, tengo el codigo asi no me sale correctamente, en consola me muestra que si se esta enviando el arreglo pero cuando envio el objeto completo no funciona average pero tu lo tienes como gradesCorrigiendo esto deberías tener un resultado diferente, espero te sea de ayuda
Un abrazo!
Este es el primer reto que completo 100% solo, estoy muy feliz, aunque tengo una duda, si intento dividir el solution.classAverage entre number de una vez dentro del ciclo for, se divide por 6 en lugar de 3, no se por que. Es por eso que tuve que ponerlo afuera de for.
<code> export function getStudentAverage(students) { let solution = { classAverage: 0, students: [] }; const length= students.length; for (let i = 0; i < students.length; i++) { const student = students[i]; let individualAverage = Number((student.grades.reduce(function (acumulator, grade) { return (acumulator + grade) }, 0) / student.grades.length).toFixed(2)); solution.classAverage = solution.classAverage + individualAverage; solution.students.push({ name: student.name, average: individualAverage }) } solution.classAverage = Number((solution.classAverage / length).toFixed(2)); return solution };
Cabe aclarar que así me funciona, solo que tengo la duda de porque no puedo ponerlo adentro. Aca les dejo la situacion en la que me devuelve solution.classAverage dividido entre 6 en lugar de 3 que es el numero de estudiantes que hay en la vista.
<code> export function getStudentAverage(students) { let solution = { classAverage: 0, students: [] }; const length = students.length; for (let i = 0; i < students.length; i++) { const student = students[i]; let individualAverage = Number((student.grades.reduce(function (acumulator, grade) { return (acumulator + grade) }, 0) / student.grades.length).toFixed(2)); solution.classAverage = Number((((solution.classAverage + individualAverage) / length).toFixed(2))); solution.students.push({ name: student.name, average: individualAverage }) } return solution };
Buenas, hay casos en el que el toFixed(2) me retorna solo un decimal después de la coma, esto me ocurre en los casos donde el segundo decimal es 0, por lo tanto, no pasa algunas de las pruebas. ¿Hay alguna manera de que redondee a dos decimales mostrando el 0 del segundo decimal?
No es necesario que se muestre el 0 ¿Cuál es la prueba que no pasa?
Tenía el error en el cálculo de los promedios de cada estudiante, al parecer era por el tipo de dato, yo efectuaba:
let promedioEstudiante = Number(sumaNotas / cantidadNotas); let studentAverage = { name: student.name, average: promedioEstudiante.toFixed(2), }
Mi error estaba en que al aplicar él .toFixed(2) a promedioEstudiante me lo volvía a dejar como String, lo arregle aplicándole de nuevo un Number() al promedio redondeado.
Aqui les dejo un pequeño aporte
My solution 👇
function getStudentAverage(students) { const result = {}; const studentAverage = []; for (let student of students) { const individualAverage = student.grades.reduce((acc, val) => val + acc, 0) / student.grades.length; studentAverage.push({ name: student["name"], average: Number(individualAverage.toFixed(2)) }); } const generalAverage = studentAverage.reduce((acc, val) => val.average + acc, 0) / studentAverage.length; result["classAverage"] = Number(generalAverage.toFixed(2)); result["students"] = studentAverage; return result; }
Reto cumplido xd:
export function getStudentAverage(students) { let datoEstudiante = []; for (var estudiante of students) { datoEstudiante.push({ name: estudiante.name, average: parseFloat(((estudiante.grades.reduce((a, b) => a + b, 0)) / estudiante.grades.length).toFixed(2)) }); } const object = { classAverage: parseFloat(((students.reduce((a, b) => a + b.grades.reduce((a, b) => a + b, 0), 0)) / students.reduce((a, b) => a + b.grades.length, 0)).toFixed(2)), students: datoEstudiante }; return object; }
no se porque qaui no me corre pero esta fue mi solucion:
export function getStudentAverage(students) { let promedioEstudiante; let promedioClase = 0; for (let i = 0; i < students.length; i++) { promedioEstudiante = +((students[i].grades.reduce((acumulador, nota) => acumulador + nota, 0) / students[i].grades.length).toFixed(2)); students[i].grades = promedioEstudiante; promedioClase += promedioEstudiante; } promedioClase = +((promedioClase / students.length).toFixed(2)); let respuesta = { classAverage: promedioClase, students: students, } return respuesta; }; ```export function getStudentAverage(students) { let promedioEstudiante; let promedioClase = 0; for (let i = 0; i < students.length; i++) { promedioEstudiante = +((students\[i].grades.reduce((acumulador, nota) => acumulador + nota, 0) / students\[i].grades.length).toFixed(2)); students\[i].grades = promedioEstudiante; promedioClase += promedioEstudiante; } promedioClase = +((promedioClase / students.length).toFixed(2)); let respuesta = { classAverage: promedioClase, students: students, } return respuesta;};
En mi editor funciona pero no se por que aqui no:
let clase = [ { name: "Pedro", grades: [90, 87, 88, 90], }, { name: "Jose", grades: [99, 71, 88, 96], }, { name: "Maria", grades: [92, 81, 80, 96], }, { name: "Mara", grades: [92, 81, 80, 96], }, { name: "Mana", grades: [92, 81, 80, 96], }, ]; let students = [...clase]; let classAverage = 0; for (i = 0; i < clase.length; i++) { let studentAverage = +((clase[i].grades.reduce((acumulador, item) => acumulador + item, 0) / clase[i].grades.length).toFixed(2)); students[i].grades = studentAverage; classAverage += studentAverage; } classAverage = (classAverage / clase.length).toFixed(2); let respuesta = {"classAverage": classAverage, "students": students}; return (respuesta);