2

I have studied C++, Java and I am learning Ruby now.
but It's hard to adapt to iteration in ruby for me yet.

n = 4
arys = Array.new(3, Array.new(n+1, 0))

for i in 1..2
    for j in 1..n
        arys[i][j] = (i-1)*n+j
    end
end

p arys

output of above code is as below

[[0, 5, 6, 7, 8], [0, 5, 6, 7, 8], [0, 5, 6, 7, 8]]

I thought it is like code as below in C

for(int i = 1; i<=2; i++)
   for(int j = 1; j<=n; j++)
       arys[i][j] = (i-1)*n+j

therefore, I expected the output will be like
[[0, 0, 0, 0, 0], [0, 1, 2, 3, 4], [0, 5, 6, 7, 8]]

what make the difference between above two codes?

2 Answers 2

6

In the very initialization line for arys you actually have created one inner array, referenced three times by arys outermost array:

arys.map &:__id__
#⇒ [
#  [0] 28193580,
#  [1] 28193580,
#  [2] 28193580
# ]

__id__ above states for unique object identifier.

To achieve the behaviour you expected, one should produce three different arrays, e.g.:

ary = Array.new(5, 0)
arys = 3.times.map { ary.dup }

Note dup above, that clones the object. Now we have three different objects (arrays)

arys.map &:__id__
#⇒ [
#  [0] 34739980,
#  [1] 34739920,
#  [2] 34739860
# ]

and your code will work as expected.

Sign up to request clarification or add additional context in comments.

2 Comments

Oh.. I didn't know that This was just duplicating single reference! Thanks!
@Stefan Indeed, I just wanted to make things as clear as possible, I corrected an answer to make dup not redundant.
1

You can also take advantage of Array#new with a block, and use below code:

arys = Array.new(3) {Array.new(n+1, 0)}

Here, we pass a block to outer array constructor so that we can create an array of size n+1 and default element values of 0 for sub-arrays (as needed in your problem statement).


Also, if you wish to use something other than for loop, here is one variant that will have same output:

(1...arys.size).each do |i|
    (1..n).each do |j|
        arys[i][j] = (i-1)*n + j
    end
end

Note use of ... in 1...arys.size to use exclusive range. 1...10 is equivalent of to 1..9, in other words (1..9).to_a == (1...10).to_a will be true

4 Comments

You can omit |i| since the argument it is not used.
@Stefan danke sehr - I always miss finer details.
Gern geschehen ;-) BTW, "whenever an index is accessed for first time" is the way Hash.new works. Array.new creates its elements immediately.
@Stefan Thanks again. I have learned a lot with feedback like this and looking at answers of others.

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.