修改二维 Ruby 数组的困难

3

抱歉问一个新手问题。我正在尝试在Ruby中创建一个二维数组,并将其所有值初始化为1。我的代码成功创建了二维数组,但未能修改任何值。

有人能解释一下我做错了什么吗?

  def mda(width,height)
     #make a two dimensional array
     a = Array.new(width)
     a.map! { Array.new(height) }

     #init all its values to 1
     a.each do |row|
       row.each do |column|
          column = 1
       end
     end
     return a
  end
4个回答

3
在代码行 row.each do |column| 中,变量 columnrow 中值的副本。你不能以这种方式编辑它的值。你必须这样做:
def mda(width,height)
  a = Array.new(width)
  a.map! { Array.new(height) }
  a.each do |row|
    row.map!{1}
  end
  return a
end

更好的做法是:
def mda(width,height)
  a = Array.new(width)
  a.map! { Array.new(height) }

  a.map do |row|
    row.map!{1}
  end
end

更好的方法是:
def mda(width,height)
  a = Array.new(width){ Array.new(height) }
  a.map do |row|
    row.map!{1}
  end
end

更好的方法是:
def mda(width,height)
  Array.new(width) { Array.new(height){1} }
end

“width”和“height”搞混了吗?此外,这可以不使用块完成:Array.new(height, Array.new(width, 1))。 - steenslag
@steenslag,不行。如果您以这种方式构建多维数组,当您为其中一个元素分配值时,它将传播到整个列。就像array = [[1]*w]*h一样,您只会制作指向相同的1维数组的“h”个副本。关于混合“宽度”和“高度”——这是另一个问题,作者没有打算讨论。 - Nakilon
请参考ghostdog74的答案。它必须至少有一个代码块。 - Nakilon

1

each 将每个元素的 传递给块参数,而不是元素本身,因此 column = 1 实际上并没有修改数组。

你可以在一步中完成这个操作 - 参见 API 文档 了解有关各种形式的 Array#new 的详细信息。尝试 a = Array.new(width) {|i| Array.new(height) {|j| 1 } }


2
当变量没有被使用时,不需要包含块变量。 - Lars Haugseth
我不知道那个。我以为它们像方法参数一样,如果它们不存在,Ruby会抱怨。啊好吧 - YLSNED! - Chowlett

0

你可以像这样创建它吗?

a=Array.new(width) { Array.new(height,1) }

-1

each循环中的column是该位置数组值的副本,而不是指针/引用,因此当您更改其值时,您只会更改副本的值(在块外部不存在)。

如果您只想要一个填充有1的二维数组,那么这样简单的代码就可以实现:

def mda(width,height)
  [ [1] * width ] * height
end

非常简单。


顺便说一下,如果你想知道如何在迭代二维数组时修改元素,这里有一种方法(从代码的第6行开始):
 #init all its values to 1
 a.length.times do |i|
   a[i].length.times do |j|
     a[i][j] = 1
   end
 end

请查看Nakilon答案下的评论:这个数组创建不起作用(尝试更改其中一个值)。 - steenslag

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接