2012-03-15 14 views
6

Estoy aprendiendo Ruby, y se ha hablado un poco sobre el método upto en el libro del que estoy aprendiendo. Estoy confundido. ¿Qué hace exactamente?El método 'upto' en Ruby

Ejemplo:

grades = [88,99,73,56,87,64] 
sum = 0 
0.upto(grades.length - 1) do |loop_index| 
    sum += grades[loop_index] 
end 
average = sum/grades.length 
puts average 
+5

Es posible que desee buscar otro libro. En este caso, este 'upto' <' grades.length.times' <'grades.each' <' grades.inject (0,: +) '. –

+0

Afortunadamente su libro no dice 'upto' es un operador; es un método regular Editó su pregunta en consecuencia. –

+1

@ Marc-AndréLafortune Muchos de los libros de Ruby son así, te dicen exactamente * qué * tiene Ruby, pero no * por qué * usarías de una forma sobre otra. :( –

Respuesta

20

Vamos a intentar una explicación:

Se define una matriz

grades = [88,99,73,56,87,64] 

y preparar una variable para almacenar la suma:

sum = 0 

grades.length es 6 (hay 6 elementos en el matriz), (grades.length - 1) es 5.

con 0.upto(5) bucle de 0 a 5, loop_index será 0, luego 1 ...

El primer elemento de la matriz es grades[0] (el índice en la matriz comienza con 0). Es por eso que tienes que restar 1 de la cantidad de elementos.

0.upto(grades.length - 1) do |loop_index| 

Agregue el valor de loop_index a sum.

sum += grades[loop_index] 
end 

Ahora bucle en cada elemento y tener la suma de todos los elementos de la matriz.

Se puede calcular el promedio:

average = sum/grades.length 

Ahora se escribe el resultado en la salida estándar:

puts average 

Este fue un no-rubí sintaxis similar . Rubí igual que lo haría así:

grades = [88,99,73,56,87,64] 
sum = 0 
grades.each do |value| 
    sum += value 
end 
average = sum/grades.length 
puts average 

Adición basado en Marc-Andrés comentario:

Es posible utilizar también inject para evitar definir la suma inicial:

grades = [88,99,73,56,87,64] 
sum = grades.inject do |sum, value|  
    sum + value 
end 
average = sum/grades.length 
puts average 

O incluso más corto:

grades = [88,99,73,56,87,64] 
average = grades.inject(:+)/grades.length 
puts average 
+0

Buena explicación. Solo agregaría que 'foo = start, enum.each {| i | foo = some_function (foo, i)}' es un patrón por el cual Rubyist puede usar 'inject'. –

+0

Gracias por la sugerencia de inyectar. Este método siempre hace nudos en mi cerebro ;) – knut

1

Hasta que ejecuta el bloque dado de una vez para cada número de la cantidad original "hasta" el argumento pasado. Por ejemplo:

1.upto(10) {|x| puts x} 

imprimirá los números del 1 al 10.

0

Una alternativa que se parece más a Ruby a mí es

require 'descriptive_statistics' 

grades=[88,99,73,56,87,64] 
sum = grades.sum 
average = grades.mean 
sd = grades.standard_deviation 

Por supuesto, depende de lo que está haciendo.

0

Mi ejemplo hubiera sido esto:

1.upto(5) { |i| puts "Countup: #{i}" } 

Así que lo que en realidad está haciendo aquí está diciendo, quiero contar desde 1 hasta el número 5, que es específicamente lo que esta parte está diciendo:

1.upto(5) 

la última parte del código (un bloque) que se acaba de dar salida a la iteración de pasar por la cuenta de 1 a 5. Esta es la salida que se podría esperar para ver:

Countup: 1 
    Countup: 2 
    Countup: 3 
    Countup: 4 
    Countup: 5 

Nota: Esto se puede escribir es otra manera si usted está utilizando líneas múltiples:

1.upto(5) do |i| 
puts "Countup: #{i}" 
end 

Espero que esto ayude.