1

I created an array by doing the following:

@gameboard = Array.new(3, Array.new(3, " "))

I tried to assign a value like so, and I got this:

@gameboard[0][2] = "X"
@gameboard #=> [[" ", " ", "X"], [" ", " ", "X"], [" ", " ", "X"]]

When I declare the array differently,

@gameboard = [[" ", " ", " "], [" ", " ", " "], [" ", " ", " "]]

I get this result:

@gameboard[0][2] = "X"
@gameboard # => [[" ", " ", "X"], [" ", " ", " "], [" ", " ", " "]]

Why does using the Array.new method illicit different behavior when assigning values to the array?

2
  • 1
    (I am sure there is a duplicate of this question.) Commented Mar 14, 2014 at 22:52
  • I definitely tried searching, I couldn't find another entry about this. Sorry if it's a duplicate! Commented Mar 14, 2014 at 23:07

2 Answers 2

8

Follow the code:

@gameboard = Array.new(3, Array.new(3, " "))
@gameboard.map { |a| a.object_id }
# => [76584030, 76584030, 76584030]

means new(size=0, obj=nil) method creates an array of size, having the same ob.

But new(size) {|index| block } method works in a different way; it creates an array of size, having different obs.

See the code below:

@gameboard = Array.new(3) { Array.new(3, " ") }
@gameboard.map { |a| a.object_id }
# => [75510080, 75509920, 75509540]

The above is the same as your second code example:

@gameboard = [[" ", " ", " "], [" ", " ", " "], [" ", " ", " "]]
@gameboard.map { |a| a.object_id }
# => [80194090, 80193400, 80193080]

If you change or update the the value at index 1 of the first element array of @gameboard, it wouldn't affect all other inner array elements.

@gameboard = Array.new(3) { Array.new(3, " ") }
@gameboard[0][1] = 2
@gameboard
# => [[" ", 2, " "], [" ", " ", " "], [" ", " ", " "]]
Sign up to request clarification or add additional context in comments.

2 Comments

+1 I had just pasted in @gameboard.map(&:object_id) when your answer showed :)
@CarySwoveland Tomorrow is weekend.. :)
1

The Array constructor will not duplicate the object you passed; it will reuse the object to fill the array.

Use the block form in order to create a new object for each index:

@gameboard = Array.new(3) { |i| Array.new(3) { |j| " " } }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.