为什么无法使用 Ruby 中的 each do 循环填充数组?

Why is it not possible to fill an array using an each do loop in Ruby?

如果我使用每个 do 循环来填充一个数组,它将保持数组原样(在本例中它将是一个大小为 4 的 nil 数组)

array = Array.new(4)
array.each do |i|
  i = 5
end

我知道我可以使用 array = Array.new(4) {desired value} 用我想要的值初始化一个数组,但在某些情况下我会在不同的值之间进行选择,并且我试图了解每个 do 循环是如何工作的。

我目前的做法是用我想要的值填充数组

array = Array.new(4)
array.each_with_index do |val, i|
  array[i] = 5
end

解决方案

你需要:

array = Array.new(4) do |i|
  5
  # or some logic depending on i (the index between 0 and 3)
end

您的代码

array = Array.new(4)

数组现在是一个包含 4 个元素的数组(每次 nil)。

array.each 迭代这 4 个元素(仍然是 nil),并将 i 设置为等于 nil.

的块局部变量

在此块中,您用 5 覆盖了 i,但您不对其进行任何操作。在下一次迭代中,i 被设置回 nil,然后是 5,依此类推...

您不更改原始数组,您只更改已设置为等于数组元素的局部变量。

区别在于

i = 5

是一项作业。它将值 5 赋给变量 i.

在Ruby中,赋值只影响局部作用域,它们不会改变调用者作用域中的变量:

def change(i)
  i = 5       # <- doesn't work as you might expect
end

x = nil
change(x)
x #=> nil

因此不可能通过分配给变量来用另一个对象替换数组元素。

另一方面,

array[i] = 5

不是赋值,而是伪装的方法调用。相当于:

array.[]=(i, 5)

array.public_send(:[]=, i, 5)

它要求数组将索引 i 处的元素设置为 5