`each`循环带有附加参数

时间:2015-11-19 02:49:00

标签: ruby loops iteration each

我希望以下row [0, 0, 0, 0]row_indexnil

img_array = [
  [0, 0, 0, 0],
  [0, 0, 0, 0],
  [0, 0, 0, 0],
  [0, 1, 0, 0],
  [0, 0, 0, 0],
  [0, 0, 0, 0]
]

img_array.each do |row, row_index|
  ...
end

实际上,row0row_index0。谁能解释一下呢?

2 个答案:

答案 0 :(得分:3)

img_array = [
  [0, 1, 2, 3],
  [4, 5, 6, 7],
  [8, 9, 0, 1]
]

我们有:

enum = img_array.each
  #=> #<Enumerator: [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 0, 1]]:each> 
因此,

Array#each创建一个枚举器,它是类Enumerator的一个实例。方法Enumerator#eachenum的每个元素传递给块并分配块变量:

enum.each { |row, row_index| puts "row=#{row}, row_index=#{row_index}" }
  # row=0, row_index=1
  # row=4, row_index=5
  # row=8, row_index=9

我们可以使用Enumerator#next方法查看enum的每个元素:

enum.next #=> StopIteration: iteration reached an end

糟糕!我忘了重置枚举器:

enum.rewind
  #=> #<Enumerator: [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 0, 1]]:each>

enum.next #=> [0, 1, 2, 3] 
enum.next #=> [4, 5, 6, 7] 
enum.next #=> [8, 9, 0, 1] 
enum.next #=> StopIteration: iteration reached an end

或者,我们可以将枚举数转换为数组(不需要rewind):

enum.to_a #=> [[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 0, 1]]

当元素([0, 1, 2, 3])传递给块时,块变量按如下方式分配:

row, row_index = [0, 1, 2, 3]            #=> [0, 1, 2, 3] 
row                                      #=> 0
row_index                                #=> 1

如果变量是|row, row_index, col_index|,则分配将是:

row, row_index, col_index = [0, 1, 2, 3] #=> [0, 1, 2, 3] 
row                                      #=> 0
row_index                                #=> 1
col_index                                #=> 2

如果他们是|row, row_index, *rest|,那就是:

row, row_index, *rest = [0, 1, 2, 3]     #=> [0, 1, 2, 3] 
row                                      #=> 0
row_index                                #=> 1
rest                                     #=> [2, 3]

这称为parallel (or multiple) assignment。您可以在我给出的链接上阅读有关此类作业的规则。

答案 1 :(得分:1)

Ruby中数组上的方法.each()将仅使用一个参数调用您的块。 所以,如果你编写这样的代码:

img_array.each do |row, row_index|
  # do something here
end

它等同于:

img_array.each do |element|
  row, row_index = element
  # and now
  # row = element[0]
  # row_index = element[1]
end

我做了一个更容易理解的例子

img_array = [
  ['a', 'b', 'd', 'e'],
  ['f', 'g', 'h', 'j']
]

img_array.each do |row, row_index|
    p row
    p row_index
end

结果将是:

"a"
"b"
"f"
"g"

在此处在线运行:https://ideone.com/ifDaVZ