嵌套数组的行为不相同

nul*_*ter 4 ruby arrays

我正在创建一个嵌套数组,以两种不同的方式存储一些字母.第一种方式是这样的:

Array.new(rows, Array.new(columns){ O })
Run Code Online (Sandbox Code Playgroud)

第二种方式是这样的:

Array.new(rows) do
  Array.new(columns) { O }
end
Run Code Online (Sandbox Code Playgroud)

它们看起来完全一样:

[["0", "0", "0", "0", "0"],
 ["0", "0", "0", "0", "0"],
 ["0", "0", "0", "0", "0"],
 ["0", "0", "0", "0", "0"],
 ["0", "0", "0", "0", "0"],
 ["0", "0", "0", "0", "0"]]
Run Code Online (Sandbox Code Playgroud)

当我想用另一个字母替换一个位置并执行:

array[1][3] = R
Run Code Online (Sandbox Code Playgroud)

使用第一种方式生成的数组,整个第一列将变为R.使用第二种方式,只有位置[1][3]将被替换为包含R.

我想知道这两种方式之间有什么区别.

Xav*_*ier 6

在第一个示例中:Array.new(rows, Array.new(columns){ O }),第二个参数指定数组的默认值作为对象引用.换句话说,在第一个示例中,您指定对每一行使用相同的确切对象,而在第二个块版本中,该表达式将针对每一行单独计算,从而为您提供可以单独更改的唯一对象.

见这里:http://ruby-doc.org/core-2.2.0/Array.html#method-c-new-label-Common+gotchas

取自以上链接:

发送第二个参数时,同一个对象将用作所有数组元素的值:

a = Array.new(2, Hash.new)
# => [{}, {}]

a[0]['cat'] = 'feline'
a # => [{"cat"=>"feline"}, {"cat"=>"feline"}]

a[1]['cat'] = 'Felix'
a # => [{"cat"=>"Felix"}, {"cat"=>"Felix"}]
Run Code Online (Sandbox Code Playgroud)

由于所有Array元素都存储相同的哈希值,因此对其中一个哈希值的更改将影响它们.

如果您想要多个副本,则应该使用每次需要初始化数组元素时使用该块结果的块版本:

a = Array.new(2) { Hash.new }
a[0]['cat'] = 'feline'
a # => [{"cat"=>"feline"}, {}]
Run Code Online (Sandbox Code Playgroud)