Strange behaviour with array of arrays

  • Thread starter Dan Stevens (IAmAI)
  • Start date
D

Dan Stevens (IAmAI)

Please observe the following code:

# Create an array of arrays by explicitly stating values
test1 = [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]
=> [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]

# Create an array of arrays using new method
test2 = Array.new(3, Array.new(3))
=> [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]

#Both arrays appear to be equal
test1 == test2 => true

# Modifying one of values behaves as expected
test1[1][1] = true => true
test1 => [[nil, nil, nil], [nil, true, nil], [nil, nil, nil]]

# Modifying one of values behaves strangely
test2[1][1] = true => true
test2 => [[nil, true, nil], [nil, true, nil], [nil, true, nil]]

Can anyone explain why this is happening as I don't understand why the
two array should behave differently? This is assuming this isn't a
bug.
 
J

James Edward Gray II

Please observe the following code:

# Create an array of arrays by explicitly stating values
test1 = [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]
=> [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]

# Create an array of arrays using new method
test2 = Array.new(3, Array.new(3))
=> [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]

#Both arrays appear to be equal
test1 == test2 => true

# Modifying one of values behaves as expected
test1[1][1] = true => true
test1 => [[nil, nil, nil], [nil, true, nil], [nil, nil, nil]]

# Modifying one of values behaves strangely
test2[1][1] = true => true
test2 => [[nil, true, nil], [nil, true, nil], [nil, true, nil]]

Can anyone explain why this is happening as I don't understand why the
two array should behave differently? This is assuming this isn't a
bug.

Let me see if I can get Ruby to explain this for you:
a = [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]] => [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]
a.map { |e| e.object_id } => [3797062, 3797052, 3797042]
a = Array.new(3, Array.new(3)) => [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]
a.map { |e| e.object_id } => [3779002, 3779002, 3779002]
a = Array.new(3) { Array.new(3) } => [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]
a.map { |e| e.object_id }
=> [3760242, 3760232, 3760222]

As you can see, the new(n, obj) constructor uses the same object over
and over again. You want the block form (shown last) instead.

James Edward Gray II
 
T

Tim Pease

Please observe the following code:

# Create an array of arrays by explicitly stating values
test1 = [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]
=> [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]

# Create an array of arrays using new method
test2 = Array.new(3, Array.new(3))
=> [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]

#Both arrays appear to be equal
test1 == test2 => true

# Modifying one of values behaves as expected
test1[1][1] = true => true
test1 => [[nil, nil, nil], [nil, true, nil], [nil, nil, nil]]

# Modifying one of values behaves strangely
test2[1][1] = true => true
test2 => [[nil, true, nil], [nil, true, nil], [nil, true, nil]]

Can anyone explain why this is happening as I don't understand why the
two array should behave differently? This is assuming this isn't a
bug.

The syntax you want is this ...

test2 = Array.new(3) {Array.new(3)}

This will create a new array of three elements and then create a a new
array object for each element of test2

test2 = Array.new(3, Array.new(3))

This will create a new array of three elements but use the same object
for element of test2

Blessings,
TwP
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,578
Members
45,052
Latest member
LucyCarper

Latest Threads

Top