From: Stefano Crocco Date: 2010-09-28T18:05:40+09:00 Subject: Re: 3x3 Array of int, changing one value affects others On Tuesday 28 September 2010, Williams Williams wrote: > |ruby-1.9.2-head > a = Array.new(3, Array.new(3, 0)) > | => [[0, 0, 0], [0, 0, 0], [0, 0, 0]] > |ruby-1.9.2-head > a[0][2] = 1 > | => 1 > |ruby-1.9.2-head > a > | => [[0, 0, 1], [0, 0, 1], [0, 0, 1]] > | > |If the values aren't all 0s, a[0][2] behaves correctly. Am I doing > |something wrong? Thanks. Array.new(size, obj) doesn't work the way you think. It creates an array with size elements, where each element is the *same object*. By same object, I don't mean different objects equal to each other, but one single object (you can see this looking at the object_id of the sub-arrays). So, it should be no wonder that modifying one of the elements also changes the others. If you want to create an array containing three different arrays [0,0,0], you need to use the block form of Array.new: Array.new(3){|i| Array.new(3,0)} This constructor creates an array of the given size, then calls the block for each index of the array and stores in that index the value returned by the block. Different from your code, now the array contains three arrays with different identities, all with the same contents. This is because every time the block is called, it returns a new array. To be more clear, your code has the same results as: # create an array of size 3 filled with nil a = Array.new(3) # create the subarray subarray = Array.new(3,0) #store the same subarray in all the three entries of the array a[0] = subarray a[1] = subarray a[2] = subarray The code which works as you want, instead, produces the same as: # create an array of size 3 filled with nil a = Array.new(3) #store in the tree entries of the array three different arrays with #the same contents a[0] = Array.new(3,0) a[1] = Array.new(3,0) a[2] = Array.new(3,0) Usually, you only use Array.new(size, obj) when obj is an immutable object, that is an object with no methods which modify it. Your use of Array.new(3,0), for instance, is correct because an Integer can't be modified. The same would be true, for example, for symbols. If obj is a mutable object, like a string, an array or a hash (which all have methods which change the object itself), creating an array this way can lead to unexpected result, as you have experienced yourself. I hope this helps Stefano