【问题标题】:An array shared despite cloning尽管克隆但共享的数组
【发布时间】:2014-04-18 17:56:04
【问题描述】:

我有这样的课:

class Tiles
  attr_accessor :board
  def initialize
    @board = Array.new(4) { Array.new(4) { 0 } }
  end
  ...

后来,我把这个方法叫做:

def display_board
  padded_board = @board.clone
  padded_board.each_with_index do |row, x|
    row.each_with_index do |item, y|
      padded_board[x][y] = pad_number(item)
    end
    puts row.join ' '
  end
end  

每当我更改padded_board@board 也会更改。我无法弄清楚为什么会这样。有什么想法吗?

【问题讨论】:

  • .dup 的执行方式相同。

标签: ruby arrays clone


【解决方案1】:

这是因为当您 clone 时,您正在创建数组 @board 的新实例,但它的元素(也是数组)不会被新实例替换。您没有深入到克隆最终元素。您需要进行深度克隆。你可能想看看herehere 建议的一些答案和宝石。

【讨论】:

  • 谢谢,有同样问题的人,这是我的解决方案:padded_board = board.map{ |row| row.clone }
【解决方案2】:

原因是数组实际上是一组指向其他对象的指针,在您的情况下,这些对象是另一个数组。当您克隆数组时,您正在创建指向相同对象的新指针。通过调用padded_board[x][y]=,您正在修改padded_board[x] 数组,@boardpadded_board 都引用了该数组。

要修复它,您不仅需要复制数组,还需要复制该数组的每个元素。在他的情况下,这应该足够了:

   padded_board = @board.map(&:clone)

在更一般的情况下,使用 deep_dup 方法扩展 Array 很有用。 Rails 在 ActiveSupport 模块中定义了这个方法,通过添加 `require 'active_support/core_ext/object/deep_dup' 也可以在任何非 Rails 项目中使用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多