I have a multi-dimension array that I have initialized using this code:
arr = Array.new(3, Array.new(3, "x"))
puts arr.inspect
# Console O/P
# [["x", "x", "x"], ["x", "x", "x"], ["x", "x", "x"]]
When I manipulate the above array, I get an unexpected response.
arr[0][0] = "y"
puts arr.inspect
# Console O/P
# [["y", "x", "x"], ["y", "x", "x"], ["y", "x", "x"]]
I cannot understand why multiple entries in the array are getting updated when I have given the exact dimension for the update.
I am referring to the Array#initialize doc.
Contrary to the above implementation, when I try to initialize the array this way and then manipulate it, I get the expected response.
arr = Array.new(3) { Array.new(3) { "x" } }
arr[0][1] = "y"
puts arr.inspect
# Console O/P
# [["x", "y", "x"], ["x", "x", "x"], ["x", "x", "x"]]
Again here, I am not sure why is the implementation different from the above initialization.
Based on my understanding, the difference between the two initializations as mentioned in the above doc is:
#new(size, default_value) ⇒ Object
#new(size) {|index| ... } ⇒ Object
I'd expect both arrays to behave in the same fashion.
The difference is that the first version re-uses the exact same array for each “line”. And therefore, changing one of the values in that array changes the array in all lines, because it is the same array.
arr = Array.new(3, Array.new(3, "x"))
arr.map(&:object_id)
#=> [31740, 31740, 31740] # All arrays are the same object
But the second version creates a new array for each line, and therefore changing one entry doesn't change the entries in the other arrays.
arr = Array.new(3) { Array.new(3) { "x" } }
arr.map(&:object_id)
#=> [81520, 81540, 81560] # Each array is a different instance