【问题标题】:How does iteration work in Ruby?Ruby 中的迭代是如何工作的?
【发布时间】:2011-03-22 07:32:57
【问题描述】:

我最近开始编写 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; "

我了解一般的哈希功能,但我不明白 valuekey 是如何设置为任何内容的。它们被指定为块中的参数,但哈希值从未以任何方式与这些参数相关联。

【问题讨论】:

  • 当它说h.each do |key,value| 时,整个do 块的key,valueh 的关联是在该行上定义的。 keyvalue 的名字可以是任何你喜欢的名字。
  • 如果h.each 看起来太神奇了,那么您可以随时使用h.each_pair
  • Ruby 带有 IRB,您可以使用 irb 从命令行运行它。它使您可以轻松地开始使用变量和赋值。当你想学习这些东西时,它是一个很好的工具。
  • 如果他们解决了您的问题,您可能希望接受答案。它们是每个问题旁边的勾号图标。

标签: ruby loops block


【解决方案1】:

这是 Ruby 块(Ruby 的匿名函数名称)语法。而keyvalue 只不过是传递给匿名函数的参数。

Hash#each 有一个参数:一个有两个参数的函数,keyvalue

因此,如果我们将其分解为多个部分,您的这部分代码:h.each,正在调用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; 

是作为参数传递给each 的函数,keyvalue 是传递给该函数的参数。不管你给它们起什么名字,第一个参数应该是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)

【讨论】:

    【解决方案2】:

    哈希 (h) 与循环相关联,因为您调用 h.each 而不是在其他东西上调用 each。它实际上是在说,“对于h 中的每个键/值对,让key 迭代变量成为键,让value 迭代变量成为值,然后执行循环体。”

    如果这没有帮助,请查看 this page on each... 如果您能详细说明您发现哪一点比较棘手,我们或许可以提供更多帮助。 (嗯,其他人也许可以。我不太了解 Ruby。)

    【讨论】:

      【解决方案3】:

      哈希确实与这些参数相关联,因为您调用 h.each 来迭代哈希:

      h.each

      如果你从数组开始,也许对你来说更容易:

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

      先玩弄这个(eacheach_with_index,...)

      【讨论】:

      • 啊,是的 - 这是有道理的。但是它怎么知道将散列的键应用于“键”并将其值应用于“值”?毕竟它们只是参数,即使哈希是关联的
      • @Joesavage1:因为你说在这里使用名称“key”和“value”:|key,value|。如果您使用|k,v|,那么变量将被称为kv
      【解决方案4】:

      当您调用h.each 时,您会说这是您希望在每次迭代中使用的特定h 哈希。 因此,当您这样做时,valuekey 变量将被一一分配给哈希中的值。

      【讨论】:

        【解决方案5】:

        我认为问题是关于变量名的。这些名字没有任何意义。只有顺序很重要。在|...|each {...} 内,键和值按此顺序给出。由于将变量名称 key 分配给 key 并将 value 分配给 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
        

        【讨论】:

          猜你喜欢
          • 2014-02-26
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-05-08
          • 1970-01-01
          相关资源
          最近更新 更多