Enlaces e información

Comenta lo que creas oportuno.


Otros posts
Sobreescribir menu links del core de Drupal 6
Hook_theme en Drupal 6

Otra manera de calcular la media ponderada en Ruby

Escrito por Roberto M. Oliva en Febrero 16th, 2009

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



Escriba un comentario

Dediquele un momento a comentar lo que piensa. Esta permitido usar HTML básico para formatear el escrito.

Comentarios de los lectores

Roberto! algunos seguimos leyéndote! :-D

La verdad es que Ruby está muy muy muy bien!

esta muy bien pero avg no es un metodo de Ruby :) lo agregamos nosotros en nuestras extensiones de la clase Array:

class Array
# Calcula la media aritmética de un array de enteros o de cualquier tipo
# que implemente sum.to_f para dar un Float
def avg
blank? and 0.0 or sum.to_f/size
end

# Permite quitar valores duplicados de un array
# especificando el atributo que hace que
# el elemento se considere duplicado
def uniq_by
seen = Set.new
select{ |x| seen.add?( yield( x ) ) }
end
end

PD: A ver si te pones un plugin de colorear ruby en el blog que estan baratos!