Is this array operation correct?

Hi,

I've tried this:

a = Array.new(3,[]) => [[], [], []]
a[1].push(3) => [[3],[3],[3]]

Is this correct? a[1].push(3) is the same as a[2].push(3)? If the
constructor creates the same copy for all array elements, shouldn’t the
array create copies when writing?

Thanks,
Maurício

Hello –

Hi,

I've tried this:

a = Array.new(3,[]) => [[], [], []]
a[1].push(3) => [[3],[3],[3]]

Is this correct? a[1].push(3) is the same as a[2].push(3)? If the
constructor creates the same copy for all array elements, shouldn’t the
array create copies when writing?

I’m not sure I follow the question, but the general thing going on is:
a[0] and a[1] and a[2] are references to the same object, so if you
change the object through one of those references, the change will be
visible in all of them.

It’s as if you said:

ar = []
a = [ ar, ar, ar ]
ar.push(3)

and then ‘a’ would look like: [[3],[3],[3]]

David

···

On Wed, 14 Aug 2002, Maurício wrote:


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

From: dblack@candle.superlink.net [mailto:dblack@candle.superlink.net]
Sent: Wednesday, August 14, 2002 4:39 AM
To: ruby-talk ML
Subject: Re: Is this array operation correct?

Hello –

Hi,

I've tried this:

a = Array.new(3,[]) => [[], [], []]
a[1].push(3) => [[3],[3],[3]]

It’s as if you said:

ar = []
a = [ ar, ar, ar ]
ar.push(3)

and then ‘a’ would look like: [[3],[3],[3]]

Then, do something like:

Array.new(3).map { [] }

Is there something shorter/more efficient?

– Christian

···

-----Original Message-----
On Wed, 14 Aug 2002, Maurício wrote:

I've tried this:

a = Array.new(3,[]) => [[], [], []]
a[1].push(3) => [[3],[3],[3]]

You may be wanting this …

a = (0…3).collect { Array.new }
a[1].push(3) => [[],[3],[]]

Yours

Chris

Array.new(3).map { [] }

Is there something shorter/more efficient?

With 1.7 you can give it a block

pigeon% ruby -ve 'a = Array.new(3) { [] }; a[1].push 1; p a'
ruby 1.7.2 (2002-08-06) [i686-linux]
[[], [1], []]
pigeon%

Guy Decoux

Then, do something like:

Array.new(3).map { [] }

Is there something shorter/more efficient?

If you don’t like using Array.new, you can #map to a Range:

(1…3).map{[]}

(Dunno about efficiency, here.)

If you’re going to map to a fresh Array, though, you may as well use the
in-place version:

Array.new(3).map!{[]}

Then, do something like:

Array.new(3).map { [] }

Is there something shorter/more efficient?

If you don’t like using Array.new, you can #map to a Range:

(1…3).map{[]}

(Dunno about efficiency, here.)

If you’re going to map to a fresh Array, though, you may as well use the
in-place version:

Array.new(3).map!{[]}

Speaking from inexperience, I doubt there’s any significant efficiency
difference between the two solutions mentioned above.

–Gavin

Really basic benchmarking (for 1.6.5 ) …

def time_it
GC.start
now = Time.now
yield
Time.now - now
end

time_it { Array.new(100000).map {[]} }
0.611
time_it { Array.new(100000).map {[]} }
0.631
time_it { (1…100000).map {[]} }
0.471
time_it { (1…100000).map {[]} }
0.471
time_it { Array.new(100000).map! {[]} }
0.351
time_it { Array.new(100000).map! {[]} }
0.361

Using map! seems the fastest way, thanks for the tip!

– Christian

···

-----Original Message-----
From: George Ogata [mailto:g_ogata@optushome.com.au]
Sent: Thursday, August 15, 2002 4:14 AM
To: ruby-talk ML
Subject: RE: Is this array operation correct?

Then, do something like:

Array.new(3).map { [] }

Is there something shorter/more efficient?

If you don’t like using Array.new, you can #map to a Range:

(1…3).map{[]}

(Dunno about efficiency, here.)

If you’re going to map to a fresh Array, though, you may as well use the
in-place version:

Array.new(3).map!{[]}