Iteration question

Dear all:

This is my code:

data = Array.new(5,[])
0.upto(4) do |i|
data[i].push(i)
end

p data

the output is :
[[0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4], [0,
1, 2, 3, 4]]

I am so confused why the output is not that showed below
[[0],[1],[2],[3],[4]]

···

--
Posted via http://www.ruby-forum.com/.

data = Array.new(5,)
This gives you array with five references to the same array object:

ruby-1.9.2-p0 :036 > data = Array.new(5,)
=> [, , , , ]

ruby-1.9.2-p0 :037 > data[0].object_id
=> 2156232780
ruby-1.9.2-p0 :038 > data[1].object_id
=> 2156232780

0.upto(4) do |i|
data[i].push(i)

no matter where you push you are still pushing to the same single array

What you want probably is:

data = Array.new(5) {}
0.upto(4) do |i|
data[i].push(i)
end
p data

In this case it is the same as

data = Array.new(5) {|index| [index]}
=> [[0], [1], [2], [3], [4]]

Regards,
Rimantas

···

From the docs:

Array.new(size=0, obj=nil)

···

--------------------------
Returns a new array. In the first form, the new array is empty. In the
second it is created with size copies of obj (that is, size references
to the same obj).
--------------------------

See the last part in parentheses? It's a stupid *feature* of ruby, and
that behaviour must have been added to the language by Matz to trip up
beginners.

--
Posted via http://www.ruby-forum.com/.

···

--
Posted via http://www.ruby-forum.com/.

Alternate way of doing the same thing:

data =
0.upto(4) { |i| data << [i] }

regards,
bbiker

···

On Mar 23, 7:20 pm, Rimantas Liubertas <riman...@gmail.com> wrote:

data = Array.new(5,)
This gives you array with five references to the same array object:

ruby-1.9.2-p0 :036 > data = Array.new(5,)
=> [, , , , ]

ruby-1.9.2-p0 :037 > data[0].object_id
=> 2156232780
ruby-1.9.2-p0 :038 > data[1].object_id
=> 2156232780

> 0.upto(4) do |i|
> data[i].push(i)

no matter where you push you are still pushing to the same single array

What you want probably is:

data = Array.new(5) {}
0.upto(4) do |i|
data[i].push(i)
end
p data

In this case it is the same as

data = Array.new(5) {|index| [index]}
=> [[0], [1], [2], [3], [4]]

Regards,
Rimantas
--http://rimantas.com/

Even simpler

irb(main):001:0> data = Array.new(5) {|i| [i]}
=> [[0], [1], [2], [3], [4]]
irb(main):002:0> data = Array.new(5) {|*a| a}
=> [[0], [1], [2], [3], [4]]
irb(main):003:0> data = 5.times.map {|i| [i]}
=> [[0], [1], [2], [3], [4]]

Kind regards

robert

···

On Thu, Mar 24, 2011 at 2:20 AM, bbiker <renard@nc.rr.com> wrote:

On Mar 23, 7:20 pm, Rimantas Liubertas <riman...@gmail.com> wrote:

data = Array.new(5,)
This gives you array with five references to the same array object:

ruby-1.9.2-p0 :036 > data = Array.new(5,)
=> [, , , , ]

ruby-1.9.2-p0 :037 > data[0].object_id
=> 2156232780
ruby-1.9.2-p0 :038 > data[1].object_id
=> 2156232780

> 0.upto(4) do |i|
> data[i].push(i)

no matter where you push you are still pushing to the same single array

What you want probably is:

data = Array.new(5) {}
0.upto(4) do |i|
data[i].push(i)
end
p data

In this case it is the same as

data = Array.new(5) {|index| [index]}
=> [[0], [1], [2], [3], [4]]

Regards,
Rimantas
--http://rimantas.com/

Alternate way of doing the same thing:

data =
0.upto(4) { |i| data << [i] }

--
remember.guy do |as, often| as.you_can - without end
http://blog.rubybestpractices.com/