Esto que escribo es un poco chorra, lo sé, pero llevo tanto tiempo sin escribir que me parece que puede ser gracioso poner esto aquí.
Hoy me he enfrentado al “terrible y dificil” reto de calcular una media ponderada de datos, más concretamente las notas de los alumnos en una asignatura.
Partimos de tener un hash en el que se define, para cada nota, los alumnos que la han obtenido. Por ejemplo (No han sacado muy buenas notas, la verdad):
{4.0=>7, 3.0=>3, 6.0=>3, 9.0=>1, 7.0=>5, 10.0=>1, 5.0=>2, 2.0=>2, 8.0=>1}
Según la definición del calculo, deberíamos acumular, por un lado, la nota multiplicada por el número de alumnos que la han obtenido y por otro el número de alumnos totales que han cursado la asignatura.
Una manera estándar de hacer esto seria:
total_peso = hash.inject(0){|result, e| result += e[0]*e[1]}
total_alumnos = hash.inject(0){|result, e| result += e[1]}
media = total_peso/total_alumnos
Hay que reconocer que ruby tiene cosas muy interesantes y que, usadas con imaginación, pueden ayudarnos a mejorar mucho el código. Y una de ellas, que es la que comento aqui, es la posibilidad de multiplicar un array por un valor. Si a cada elemento del hash multiplicamos la nota convertida en array por el número de alumnos que han obtenido esa nota obtendremos un array con todas las notas de todos los alumnos. A partir de ahí basta aplicar el método avg del Array para que Ruby calcule la media. Esto es lo mismo que antes, pero reduciendo enormemente el código:
hash.map{|k,v| [k] * v}.flatten.avg
Enviar un comentario nuevo