2011-03-22 23 views
5

Recientemente he empezado a codificar Ruby y tengo un malentendido con los parámetros del bloque. Tome el siguiente código de ejemplo:¿Cómo funciona la iteración en Ruby?

h = { # A hash that maps number names to digits 
:one => 1, # The "arrows" show mappings: key=>value 
:two => 2 # The colons indicate Symbol literals 
} 
h[:one] # => 1. Access a value by key 
h[:three] = 3 # Add a new key/value pair to the hash 
h.each do |key,value| # Iterate through the key/value pairs 
    print "#{value}:#{key}; " # Note variables substituted into string 
end # Prints "1:one; 2:two; 3:three; " 

entiendo la funcionalidad general de hash, sin embargo yo no entiendo cómo value y key se establecen para nada. Se especifican como parámetros en el bloque, pero el hash nunca se asocia de ninguna manera con estos parámetros.

+1

Cuando dice 'h.each hacer | clave, valor |' 'la asociación de clave, valor' a' H' para todo el bloque 'do' se define en esa línea. Los nombres 'key' y' value' podrían ser lo que quieras. –

+0

Si 'h.each' parece demasiado mágico para entonces siempre puedes usar' h.each_pair'. –

+0

Ruby viene con IRB, que puedes ejecutar desde la línea de comando usando 'irb'. Te permite comenzar a jugar fácilmente con variables y asignaciones. Es una gran herramienta cuando quieres aprender este tipo de cosas. –

Respuesta

6

Esta es la sintaxis del bloque Ruby (nombre de Ruby para una función anónima). Y key, value no son más que los argumentos pasados ​​a la función anónima.

Hash#each toma un parámetro: una función que tiene 2 parámetros, key y value.

Si lo descomponemos en partes, esta parte de su código: h.each, llama a la función each en h. Y esta parte de su código:

do |key, value| # Iterate through the key/value pairs 
    print "#{value}:#{key}; " # Note variables substituted into string 
end # Prints "1:one; 2:two; 3:three; 

es la función pasada a each como un argumento y key, value son argumentos que se pasan a esta función. No importa cómo los nombre, el primer argumento esperado es clave y el segundo argumento esperado es valor.

Permite dibujar algunas analogías.Considere una función básica:

def name_of_function(arg1, arg1) 
    # Do stuff 
end 

# You'd call it such: 
foo.name_of_function bar, baz # bar is becomes as arg1, baz becomes arg2 

# As a block: 

ooga = lambda { |arg1, arg2| 
    # Do stuff 
} 

# Note that this is exactly same as: 

ooga = lambda do |arg1, arg2| 
    # Do stuff 
end 

# You would call it such: 

ooga.call(bar, baz) # bar is becomes as arg1, baz becomes arg2 

Así que su código también se puede escribir como:

print_key_value = lambda{|arg1, arg2| print "#{arg1}:#{arg2}"} 
h = { 
    :one => 1, 
    :two => 2 
} 

h.each &print_key_value 

Hay varias formas en las que el código dentro de un bloque puede ejecutar:

yield 
    yield key, value # This is one possible way in which Hash#each can use a block 
    yield item 

    block.call 
    block.call(key, value) # This is another way in which Hash#each can use a block 
    block.call(item) 
6

El hash (h) está asociado al ciclo debido a que usted llama al h.each en lugar de llamar al each en otra cosa. De hecho dice: "Para cada par clave/valor en h, deje que la variable de iteración key sea la clave, deje que la variable de iteración value sea el valor, luego ejecute el cuerpo del ciclo".

Si eso no ayuda, échele un vistazo a this page on each ... y si puede explicar más sobre qué bit está encontrando complicado, podremos ayudarlo más. (Bueno, otros pueden hacerlo. Realmente no conozco a Ruby.)

0

cuando llamas al h.each, ahí es cuando dices que este es el hash h específico que deseas usar para cada iteración. Por lo tanto, cuando lo haga, las variables value y key se asignan a los valores en su hash, uno por uno.

1

El hash es, en efecto asociado con estos parámetros, ya que se llama h.each para iterar sobre el hash:

h.each < - aquí está el enlace se echa en falta

Tal vez sea más fácil para usted si usted comenzar con una matriz en lugar:

a = [1,2,3] 
a.each do |v| 
    puts v 
end 

y jugar con esta primera (each, each_with_index, ...)

+0

Ah sí, eso tiene sentido. Pero, ¿cómo sabe aplicar la clave del hash a "clave" y su valor a "valor"? Después de todo, son solo parámetros, incluso si el hash está asociado –

+1

@ Joesavage1: Porque está diciendo que use los nombres "clave" y "valor" aquí: '| clave, valor |'. Si usó '| k, v |', entonces las variables se llamarían 'k' y' v' en su lugar. –

0

Creo que la pregunta es sobre los nombres de las variables. Los nombres no tienen significado. Solo el orden importa. Dentro de |...| dentro de each {...}, la clave y el valor se dan en ese orden. Dado que es natural asignar el nombre de la variable key a la clave y value al valor, a menudo lo encontrará hecho así. De hecho, puede ser cualquier otra cosa.

each{|k, v| ...} # k is key, v is value 
each{|a, b| ...} # a is key, b is value 

o incluso engañosa:

each{|value, key| ...} # value is key, key is value 
Cuestiones relacionadas