¿Cómo conseguiría encontrar un promedio de una matriz?
Si tengo la matriz:
[0,4,8,2,5,0,2,6]
El promedio me daría 3.375.
ruby-on-rails
ruby
punteado
fuente
fuente

Respuestas:
Prueba esto:
Tenga en cuenta
.to_flo que querrá para evitar cualquier problema de la división de enteros. También puedes hacer:Puede definirlo como parte de lo
Arrayque sugirió otro comentarista, pero debe evitar la división de enteros o sus resultados serán incorrectos. Además, esto generalmente no es aplicable a todos los tipos de elementos posibles (obviamente, un promedio solo tiene sentido para cosas que se pueden promediar). Pero si quieres ir por esa ruta, usa esto:Si no lo has visto
injectantes, no es tan mágico como podría parecer. Se itera sobre cada elemento y luego le aplica un valor acumulador. El acumulador se entrega al siguiente elemento. En este caso, nuestro acumulador es simplemente un número entero que refleja la suma de todos los elementos anteriores.Editar: El comentarista Dave Ray propuso una buena mejora.
Editar: La propuesta del comentarista Glenn Jackman, usando
arr.inject(:+).to_f, también es buena, pero tal vez un poco demasiado inteligente si no sabes lo que está sucediendo. El:+es un símbolo; cuando se pasa a inyectar, aplica el método nombrado por el símbolo (en este caso, la operación de suma) a cada elemento contra el valor del acumulador.fuente
arr.inject(0.0) { |sum,el| sum + el } / arr.size.injectinterfaz, mencionada en la documentación. Elto_procoperador es&.Array#injectes excesivo aquí. Solo úsalo#sum. Por ejemploarr.sum.to_f / arr.sizeUna versión de esto que no use
instance_evalsería:fuente
instance_evalle permite ejecutar el código mientras solo especificaauna vez, para que pueda encadenarse con otros comandos. Es decir, enrandom_average = Array.new(10) { rand(10) }.instance_eval { reduce(:+) / size.to_f }lugar derandom = Array.new(10) { rand(10) }; random_average = random.reduce(:+) / random.sizeselfdentro de ese bloque, te encontrarás con problemas).instance_evalEs más para metaprogramación o DSL.Creo que la respuesta más simple es
fuente
reducees un método deEnumerablemezcla utilizado porArray. Y a pesar de su nombre, estoy de acuerdo con @ShuWu ... a menos que esté usando Rails que implementasum.Esperaba Math.average (valores), pero no tuve tanta suerte.
fuente
summétodo, por lo que parece ser una respuesta correcta después de 6 años, digna del premio Nostradamus.Las versiones de Ruby> = 2.4 tienen un método de suma # Enumerable .
Y para obtener el promedio de coma flotante, puede usar Integer # fdiv
Para versiones anteriores:
fuente
Algunos puntos de referencia de las mejores soluciones (en orden de la más eficiente):
Gran matriz:
Pequeñas matrices:
fuente
fuente
nillugar de 0?Permítanme traer algo a la competencia que resuelve el problema de división por cero:
Sin embargo, debo admitir que "intentar" es un ayudante de Rails. Pero puedes resolver esto fácilmente:
Por cierto: creo que es correcto que el promedio de una lista vacía sea nulo. El promedio de nada es nada, no 0. Entonces, ese es el comportamiento esperado. Sin embargo, si cambia a:
el resultado para las matrices vacías no será una excepción como esperaba, sino que devuelve NaN ... Nunca lo había visto antes en Ruby. ;-) Parece ser un comportamiento especial de la clase Float ...
fuente
lo que no me gusta de la solución aceptada
es que realmente no funciona de una manera puramente funcional. necesitamos una variable arr para calcular arr.size al final.
Para resolver esto de manera puramente funcional, necesitamos hacer un seguimiento de dos valores: la suma de todos los elementos y el número de elementos.
Santhosh mejoró esta solución: en lugar de que el argumento r sea una matriz, podríamos usar la desestructuración para separarlo inmediatamente en dos variables
si quieres ver cómo funciona, agrega algunas opciones:
También podríamos usar una estructura en lugar de una matriz para contener la suma y el recuento, pero luego tenemos que declarar la estructura primero:
fuente
end.methoden rubí, ¡gracias por esto!arr.inject([0.0,0]) { |(sum, size), el| [ sum + el, size + 1 ] }.inject(:/)Para diversión pública, otra solución más:
fuente
No tenga Ruby en esta PC, pero algo en esta medida debería funcionar:
fuente
Añadir
Array#average.Estaba haciendo lo mismo con bastante frecuencia, así que pensé que era prudente extender la
Arrayclase con unaveragemétodo simple . No funciona para nada más que una matriz de números como enteros o flotantes o decimales, pero es útil cuando lo usa correctamente.Estoy usando Ruby on Rails, así que coloqué esto
config/initializers/array.rbpero puedes colocarlo en cualquier lugar que esté incluido en el arranque, etc.config/initializers/array.rbfuente
fuente
Resuelve dividir por cero, división entera y es fácil de leer. Se puede modificar fácilmente si elige que una matriz vacía devuelva 0.
También me gusta esta variante, pero es un poco más prolija.
fuente
fuente
Este método puede ser útil.
fuente
Sin tener que repetir la matriz (p. Ej., Perfecta para líneas simples):
fuente
Corto pero usando variable de instancia
fuente
a_size = nil; [1,2].tap { |a| a_size = a.size }.inject(:+).to_f/a_sizelugar de crear una variable de instancia.Podría intentar algo como lo siguiente:
fuente