Multi-dimension array

Hi there,

I am a little confused about multi-dimension array definition in ruby.
I tried the following

a=Array.new(3,Array.new(2,Array.new))
p a

out put is:
[[[ ], [ ]], [[ ], [ ]], [[ ], [ ]]]

What I need is a 2 dimesional array a, with the following elements

a[0][0]
a[0][1]
a[1][0]
a[1][1]
a[2][0]
a[2][1]

I try to use a[i][0] << aNumber in a for loop …

Is it right? Anyway, in the program, it is not giving out result I
expected. :frowning:

Thanks
Shannon

“Shannon Fang” xrfang@hotmail.com wrote in message
news:20021208193614.A604.XRFANG@hotmail.com

Hi there,

I am a little confused about multi-dimension array definition in ruby.

It’s OK … it is confusing in the beginning to most of us (especially if
coming from C background)

I tried the following
a=Array.new(3,Array.new(2,Array.new))
p a

out put is:
[[, ], [, ], [, ]]

Correct ! It did what you asked it do … reading Array.new from inside out:
First create an Array object with no elements (like )
Then use it as the initial value of another Array object with 2 elements.
Then use this as the initial value of the final Array object with 3
elements.

Hence:

[[, ], [, ], [, ]]

Moreover, if you tried:

a[0][0][0] = 1
p a

you would now get

[[[1], [1]], [[1], [1]], [[1], [1]]]

Surprised, eh ?

What I need is a 2 dimesional array a, with the following elements
a[0][0]
a[0][1]
a[1][0]
a[1][1]
a[2][0]
a[2][1]

Then you should try :

a = Array.new(2,Array.new(2,0))
p a

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

But then again,

a[0][0] = 1
p a

will give you :

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

So the other approach is:

arr = Array.new(2)
arr.each_index { |i|
r = Array.new(2)
r.each_index { |j|
r[j] = 0
}
arr[i] = r
}
p arr

will give you:

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

Now if you do:

arr[0][0] = 1
p arr

you will get:

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

Is that what you wanted ?

HTH,
– shanko

Hi,

···

On Mon, 9 Dec 2002 07:23:22 +0900 “Shashank Date” sdate@kc.rr.com wrote:

I tried the following
a=Array.new(3,Array.new(2,Array.new))
p a

out put is:
[[, ], [, ], [, ]]

Correct ! It did what you asked it do … reading Array.new from inside out:
First create an Array object with no elements (like )
Then use it as the initial value of another Array object with 2 elements.
Then use this as the initial value of the final Array object with 3
elements.

Hence:

[[, ], [, ], [, ]]

Moreover, if you tried:

a[0][0][0] = 1
p a

you would now get

[[[1], [1]], [[1], [1]], [[1], [1]]]

Surprised, eh ?
I’m indeed surprised by this piculiar behavior. I used the solution you
suggested, it worked fine. tks. But I don’t understand why?

Shannon

Hi –

···

On Mon, 9 Dec 2002, Shashank Date wrote:

So the other approach is:

arr = Array.new(2)
arr.each_index { |i|
r = Array.new(2)
r.each_index { |j|
r[j] = 0
}
arr[i] = r
}
p arr

will give you:

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

You’re doing too much work – let Ruby do it :slight_smile:

arr = (1…3).map { [0,0] }

David


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

dblack@candle.superlink.net wrote in message

You’re doing too much work – let Ruby do it :slight_smile:

arr = (1…3).map { [0,0] }

Well, I was following the KISS principle : Keep it simple and stupid
and you followed the KISS principle: Keep it simple and smart :wink:

Thanks for the excellent example of The Ruby way !

– shanko

“Shannon Fang” xrfang@hotmail.com wrote in message

Surprised, eh ?
I’m indeed surprised by this piculiar behavior. I used the solution you
suggested, it worked fine. tks. But I don’t understand why?

The way I see it is by understanding that if you make the second argument
of Array.new to be another array
(like Array.new(3,Array.new)), only one instance of the Array is created
and its ** reference ** is copied across all the elements.

So, just as
Array(3,0) will create [0,0,0]
Array(3, Array.new) will create [,,]
But all the three arrays in this case ^^^^^
will be refering to only ONE instance (object).
Hence changing any one of them will change all three !

The same logic applies when you do Array.new(3, Array(3, Array.new))

If you study the second solution carefully, you will see that it forces you
to create distinct objects every time. No messing with the references. Hence
you can change any one object without affecting the others.

And as pointed to by David, this can be all done in the single line

a = (1…3).collect { [0,0,0]}
p a # will give [[0,0,0],[0,0,0],[0,0,0]]

HTH,
– shanko