Как работает итерация в Ruby? - PullRequest
5 голосов
/ 22 марта 2011

Я недавно начал кодировать 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; "

Я понимаю общие функции хеширования, однако не понимаю, как value и key установлены на что-либо. Они указываются в качестве параметров в блоке, но хеш никак не связан с этими параметрами.

Ответы [ 5 ]

6 голосов
/ 22 марта 2011

Это синтаксис блока Ruby (имя Ruby для анонимной функции). И key, value - это не что иное, как аргументы, передаваемые анонимной функции.

Hash#each принимает один параметр: функция, которая имеет 2 параметра, key и value.

Так что, если мы разобьем его на части, эта часть вашего кода: h.each вызывает функцию each для h. И эта часть вашего кода:

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; 

- это функция, передаваемая each в качестве аргумента, а key, value - аргументы, передаваемые этой функции. Неважно, как вы их называете, первый ожидаемый аргумент - ключ , а второй ожидаемый аргумент - значение .

Давайте проведем некоторые аналогии. Рассмотрим основную функцию:

 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

Таким образом, ваш код также может быть записан как:

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

h.each &print_key_value

Существует несколько способов выполнения кода внутри блока:

  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 голосов
/ 22 марта 2011

Хеш (h) связан с циклом из-за того, что вы вызываете h.each вместо вызова each в другом месте.Фактически он говорит: «Для каждой пары ключ / значение в h, пусть итерационная переменная key будет ключом, пусть итерационная переменная value будет значением, а затем выполните тело цикла».

Если это не поможет, взгляните на эту страницу на each ... и если вы сможете объяснить больше о том, какой бит вы считаете хитрым, мы можем помочьБольше.(Ну, другие могут. Я действительно не знаю Руби.)

1 голос
/ 22 марта 2011

Хеш действительно связан с этими параметрами, потому что вы вызываете h.each для итерации по хешу:

h.each <- вот ссылка, которую вам не хватает </p>

Возможно, вам будет проще, если вы начнете с массива:

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

и поиграйте с этим первым (each, each_with_index, ...)

0 голосов
/ 22 марта 2011

Я думаю, что вопрос об именах переменных. Имена не имеют значения. Только заказ имеет значение. Внутри |...| внутри each {...} ключ и значение указываются в этом порядке. Поскольку естественно присвоить имя переменной key ключу и значение value, вы часто делаете это так. На самом деле, это может быть что-то еще.

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

или даже обманчиво:

each{|value, key| ...} # value is key, key is value
0 голосов
/ 22 марта 2011

когда вы вызываете h.each, именно тогда вы говорите, что это именно тот h хеш, который вы хотите использовать для каждой итерации.Следовательно, когда вы делаете это, переменные value и key присваиваются значениям в вашем хэше, один за другим.

...