为什么此数组初始化的行为有所不同?

时间:2014-05-18 20:12:16

标签: ruby arrays initialization

我有

def initialize
  @board = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]] 
end

我以为我可以缩短它:

def initialize
  @board=[ [0] * 4] * 4
end

它们看起来一样,但只有后者,我得到一个错误,如:

10) vertical turn can add 1 to an existing column of 2 with 1's at the ends                                             [20/18949]
   Failure/Error: expect([game.board[0][2], game.board[1][2], game.board[2][2], game.board[3][2]]).to eq [0,1,0,0]

     expected: [0, 1, 0, 0]
          got: [1, 1, 0, 1]

     (compared using ==)
   # ./spec/game_spec.rb:132:in `block (2 levels) in <top (required)>'

1 个答案:

答案 0 :(得分:5)

请尝试使用此工作和非工作代码:

@board.map { |x| x.object_id }

你会发现差异。发生错误是因为所有内部数组都是同一个对象。

问题在于

[ [0] * 4 ] * 4

是一个包含相同数组四次的数组。

虽然

[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]

是一个包含四个不同Array对象的Array。

当你.inspect时,它们看起来是一样的,因为Ruby没有向你显示对象ID。

实现0-ed数组的另一种方法可能是:

Array.new(4) { Array.new(4) {0} }

或者,如果您只处理4x4整数,那么您可以查看narray库,它没有这些问题,而且批量操作也非常快。