Nihongo (Japanese)

Initialization of multi-dimensional array

I wanted to process data of PBM image using a double array (an array of arrays). When I thought of the initilization of a double array, the code as below first came to my mind.

ar = Array.new(4, Array.new(0, 4))

It is intended to initialize a double array ar of 4 x 4 with 0. It seems simple and smart :-). But, I found something strange with a double array ar...

$ irb 
irb(main):001:0> ar = Array.new(4, Array.new(4, 0))       # initialization
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
irb(main):002:0> ar[1][1] = 2                             # substitution
2
irb(main):003:0> p ar
[[0, 2, 0, 0], [0, 2, 0, 0], [0, 2, 0, 0], [0, 2, 0, 0]]  # ??
nil

I thought only ar[1] was changed by ar[1][1] = 2, however, other arrays were also changed like ar[1].

I couldn't find the reason for a while. But finally, I found the answer in Ruby FAQ 2.12. When the array ar is initialized as above, all of the elements of ar point to the same object (Array.new(4, 0)). Therefore, the operations to one element seem to affect all of the elements.

In order to avoid this, the array ar should be initialized so that each of the elements of ar point to different array. For, example..

$ irb 
irb(main):001:0> ar = Array.new(4).collect { Array.new(4, 0) } # init
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
irb(main):002:0> ar[1][1] = 2
2
irb(main):003:0> p ar
[[0, 0, 0, 0], [0, 2, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]] # seems good
nil

But, it is easier to use mdarray in some cases. When you access out of the range specified at initialization, an exception is raised.



[Rabbit Mark] Feel free to mail me

sato.mshr@gmail.com