Dumb "array of arrays" question

Discussion in 'Ruby' started by RichardOnRails, Aug 25, 2008.

  1. Hi,

    I wrote the following intending to create an array of 3 element, each
    being itself an array of two elements initialized to zero; Judging by
    "inspect", I seem to have that:

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

    I tried the following, which confirms that a[0] is indeed a sub-
    array.

    a[0].inspect + "; " + a[0].class.to_s => [0, 0]; Array

    Then I tried to assign a number (5) to the first element of the first
    sub-array. What I got was more 5's than I bargained for:

    a[0][0]=5 => [[5, 0], [5, 0], [5, 0]]

    What am I missing here?

    Thanks in Advance,
    Richard
     
    RichardOnRails, Aug 25, 2008
    #1
    1. Advertising

  2. On Mon, Aug 25, 2008 at 6:55 PM, RichardOnRails
    <> wrote:
    > Hi,
    >
    > I wrote the following intending to create an array of 3 element, each
    > being itself an array of two elements initialized to zero; Judging by
    > "inspect", I seem to have that:
    >
    > a = Array.new(3, [0,0]) => [[0, 0], [0, 0], [0, 0]]
    >
    > I tried the following, which confirms that a[0] is indeed a sub-
    > array.
    >
    > a[0].inspect + "; " + a[0].class.to_s => [0, 0]; Array
    >
    > Then I tried to assign a number (5) to the first element of the first
    > sub-array. What I got was more 5's than I bargained for:
    >
    > a[0][0]=5 => [[5, 0], [5, 0], [5, 0]]
    >
    > What am I missing here?
    >

    Use the block form of Array.new

    a = Array.new(3) { [0, 0] }
    a[0][0] = 5

    HTH,
    Michael Guterl
     
    Michael Guterl, Aug 26, 2008
    #2
    1. Advertising

  3. RichardOnRails

    Chris Shea Guest

    On Aug 25, 4:57 pm, RichardOnRails
    <> wrote:
    > Hi,
    >
    > I wrote the following intending to create an array of 3 element, each
    > being itself an array of two elements initialized to zero;  Judging by
    > "inspect", I seem to have that:
    >
    > a = Array.new(3, [0,0]) => [[0, 0], [0, 0], [0, 0]]
    >
    > I tried the following,  which confirms that a[0] is indeed a sub-
    > array.
    >
    > a[0].inspect + "; " + a[0].class.to_s => [0, 0]; Array
    >
    > Then I tried to assign a number (5) to the first element of the first
    > sub-array. What I got was more 5's than I bargained for:
    >
    > a[0][0]=5 => [[5, 0], [5, 0], [5, 0]]
    >
    > What am I missing here?
    >
    > Thanks in Advance,
    > Richard


    This is a gotcha that trips up everyone the first time they come
    across it. Array.new(size, obj) creates a new array with _size_ copies
    of _obj_. That is, your array has three copies of the array [0,0].
    Each one is the same as the other. So when you assign to the first
    element of that array, all copies get updated. You'll want to use
    Array.new with a block to get different objects:

    a = Array.new(3, [0,0])
    a # => [[0, 0], [0, 0], [0, 0]]
    a.map {|element| element.object_id} # => [78860, 78860, 78860]

    a2 = Array.new(3) {[0,0]}
    a2 # => [[0, 0], [0, 0], [0, 0]]
    a2.map {|element| element.object_id} # => [77710, 77700, 77690]

    a2[0][0] = 5
    a2 # => [[5, 0], [0, 0], [0, 0]]

    HTH,
    Chris
     
    Chris Shea, Aug 26, 2008
    #3
  4. RichardOnRails

    Todd Benson Guest

    On Mon, Aug 25, 2008 at 6:07 PM, Michael Guterl <> wrote:
    > On Mon, Aug 25, 2008 at 6:55 PM, RichardOnRails
    > <> wrote:
    >> Hi,
    >>
    >> I wrote the following intending to create an array of 3 element, each
    >> being itself an array of two elements initialized to zero; Judging by
    >> "inspect", I seem to have that:
    >>
    >> a = Array.new(3, [0,0]) => [[0, 0], [0, 0], [0, 0]]
    >>
    >> I tried the following, which confirms that a[0] is indeed a sub-
    >> array.
    >>
    >> a[0].inspect + "; " + a[0].class.to_s => [0, 0]; Array
    >>
    >> Then I tried to assign a number (5) to the first element of the first
    >> sub-array. What I got was more 5's than I bargained for:
    >>
    >> a[0][0]=5 => [[5, 0], [5, 0], [5, 0]]
    >>
    >> What am I missing here?
    >>

    > Use the block form of Array.new
    >
    > a = Array.new(3) { [0, 0] }
    > a[0][0] = 5


    There's also...

    inner_dim = 2
    inner_val = 0
    outer_dim = 3
    a = Array.new(outer_dim) { Array.new(inner_dim, inner_val) }

    Why would someone do it this way? Because you can change what's
    inside the new() instead of steadfastly saying it must be [0, 0].
    Sort of moving data away from logic a little. Easier to debug, blah,
    blah...

    If that's not really a big deal, I would go Michael's and Chris's route.

    Todd
     
    Todd Benson, Aug 26, 2008
    #4
  5. On Aug 25, 6:57 pm, RichardOnRails
    <> wrote:
    > Hi,
    >
    > I wrote the following intending to create an array of 3 element, each
    > being itself an array of two elements initialized to zero; Judging by
    > "inspect", I seem to have that:
    >
    > a = Array.new(3, [0,0]) => [[0, 0], [0, 0], [0, 0]]
    >
    > I tried the following, which confirms that a[0] is indeed a sub-
    > array.
    >
    > a[0].inspect + "; " + a[0].class.to_s => [0, 0]; Array
    >
    > Then I tried to assign a number (5) to the first element of the first
    > sub-array. What I got was more 5's than I bargained for:
    >
    > a[0][0]=5 => [[5, 0], [5, 0], [5, 0]]
    >
    > What am I missing here?
    >
    > Thanks in Advance,
    > Richard


    Hi y'all,

    Many thanks.
    Thanks to Michael for being first with a quick solution
    Thanks to Todd for suggesting what might be more elegant in certain
    circumstances.
    Thanks to Chris for revealing exact how Ruby handles my construct and
    the one I really want.

    Best wishes,
    Richard
     
    RichardOnRails, Aug 26, 2008
    #5
  6. RichardOnRails

    Thomas B. Guest

    Thomas B., Aug 26, 2008
    #6
  7. On Aug 26, 8:26 am, "Thomas B." <> wrote:
    > RichardOnRails wrote:
    > > a[0][0]=5 => [[5, 0], [5, 0], [5, 0]]

    >
    > You might want to have a look at the posthttp://al2o3-cr.blogspot.com/2008/08/object-arr.htmldescribing nicely
    > some details about pointers in Ruby. Might be a good addition to what
    > has already been said here.
    > --
    > Posted viahttp://www.ruby-forum.com/.


    Hi Thomas,

    Thanks for the link, which offers a lot of interesting things. On
    aesthetic grounds, I'd like a white background. The black is tough
    on a septuagenarian :)

    But I have a more substantive question. The site says:

    <quote>
    [x] #=> [#<Object:0x2d8ce10>]
    [x].dup #=> [#<Object:0x2d8ce10>]

    As you see,

    dup on an object makes a new object (the addresses differ) [referring
    to earlier statements], but

    dup on an array makes a new array but does not make a copy of the
    elements - it just makes a new array with its elements pointing to the
    original objects.
    </quote>

    My minor exception is that an array IS an object, so the two
    paragraphs sound weird. He is contrasting an object of class Object
    to an object of class Array.

    More importantly, according to my tests below, dup'ing an array does
    NOT make a new array. It returns the (address of/pointer to) the same
    old array.

    I am missing something?

    Best wishes,
    Richard

    Code
    ====
    x = Object.new
    puts "1: " + x.inspect
    puts "2: " + x.dup.inspect

    a = [x]
    ad = a.dup
    puts "3: " + a.inspect+ "; " + a[0].inspect + "; " + a.class.to_s
    puts "4: " + ad.inspect + "; " + ad[0].inspect + "; " + ad.class.to_s

    Output
    ======
    1: #<Object:0x2808138>
    2: #<Object:0x28080c0>
    3: [#<Object:0x2808138>]; #<Object:0x2808138>; Array
    4: [#<Object:0x2808138>]; #<Object:0x2808138>; Array
     
    RichardOnRails, Aug 28, 2008
    #7
  8. RichardOnRails

    Thomas B. Guest

    Hello Richard,

    RichardOnRails wrote:
    > My minor exception is that an array IS an object, so the two
    > paragraphs sound weird. He is contrasting an object of class Object
    > to an object of class Array.
    >
    > More importantly, according to my tests below, dup'ing an array does
    > NOT make a new array. It returns the (address of/pointer to) the same
    > old array.


    dup'ing an array DOES make a new array, only the new array looks like
    the old one, because Array#inspect doesn't return the address of the
    array so you cannot see if it is exactly the same instance or not. But
    there is a method to check it: equal?. It works like == in Java.

    a=[whatever]
    a.equal?(a) #=> true # the very same Array instance
    a.equal?(a.dup) #=> false # it's another instance, only it looks like
    the old one when inspect'ed

    But still the whatever inside a and a.dup is exactly the same thing:
    a[0].euqal?(a.dup[0]) #=> true

    That proves the copy is shallow - there's a new object, but it holds old
    references.

    > 3: [#<Object:0x2808138>]; #<Object:0x2808138>; Array
    > 4: [#<Object:0x2808138>]; #<Object:0x2808138>; Array


    The [#<Object:0x2808138>]'s here are in fact different objects, only
    they look the same.

    Hope that helps a bit.

    T.
    --
    Posted via http://www.ruby-forum.com/.
     
    Thomas B., Aug 28, 2008
    #8
  9. RichardOnRails

    Adam Shelly Guest

    On 8/28/08, Thomas B. <> wrote:
    > Hello Richard,
    >
    > RichardOnRails wrote:
    > > More importantly, according to my tests below, dup'ing an array does
    > > NOT make a new array. It returns the (address of/pointer to) the same
    > > old array.

    >
    > dup'ing an array DOES make a new array, only the new array looks like
    > the old one, because Array#inspect doesn't return the address of the
    > array so you cannot see if it is exactly the same instance or not.


    > > 3: [#<Object:0x2808138>]; #<Object:0x2808138>; Array
    > > 4: [#<Object:0x2808138>]; #<Object:0x2808138>; Array

    >
    > The [#<Object:0x2808138>]'s here are in fact different objects, only
    > they look the same.
    >

    You can prove they are different objects this way:
    code:
    a = [Object.new]; ad = a.dup
    puts a.inspect+ ", #{a.object_id}"
    puts ad.inspect+ ", #{ad.object_id}"
    output:
    [#<Object:0x2842310>], 21107090
    [#<Object:0x2842310>], 21107070

    -Adam
     
    Adam Shelly, Aug 28, 2008
    #9
  10. On Aug 28, 1:07 pm, Adam Shelly <> wrote:
    > On 8/28/08, Thomas B. <> wrote:
    >
    >
    >
    > > Hello Richard,

    >
    > > RichardOnRails wrote:
    > > > More importantly, according to my tests below, dup'ing an array does
    > > > NOT make a new array. It returns the (address of/pointer to) the same
    > > > old array.

    >
    > > dup'ing an array DOES make a new array, only the new array looks like
    > > the old one, because Array#inspect doesn't return the address of the
    > > array so you cannot see if it is exactly the same instance or not.
    > > > 3: [#<Object:0x2808138>]; #<Object:0x2808138>; Array
    > > > 4: [#<Object:0x2808138>]; #<Object:0x2808138>; Array

    >
    > > The [#<Object:0x2808138>]'s here are in fact different objects, only
    > > they look the same.

    >
    > You can prove they are different objects this way:
    > code:
    > a = [Object.new]; ad = a.dup
    > puts a.inspect+ ", #{a.object_id}"
    > puts ad.inspect+ ", #{ad.object_id}"
    > output:
    > [#<Object:0x2842310>], 21107090
    > [#<Object:0x2842310>], 21107070
    >
    > -Adam


    Hi Adam,

    Thanks for example. My mistake was thinking that a.inspect, which
    yielded [#<Object:0x2842310>] was yielding the a's object_id.

    I speculated that inspect yielded its receiver's content's object_id.
    That's wrong, as evidenced by the following code. So is inspect
    returning in this instance?

    Best wishes,
    Richard

    a = [x]
    ad = a.dup

    puts "1: " + a.object_id.to_s+ "; " + a[0].object_id.to_s + "; " +
    a.inspect
    puts "2: " + ad.object_id.to_s + "; " + ad[0].object_id.to_s + "; " +
    ad.inspect

    1: 20987380; 20987470; [#<Object:0x2807c9c>]
    2: 20987370; 20987470; [#<Object:0x2807c9c>]
     
    RichardOnRails, Aug 28, 2008
    #10
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Mark Healey

    Probably a dumb s/// question.

    Mark Healey, Mar 16, 2005, in forum: Perl
    Replies:
    2
    Views:
    531
    Glenn Jackman
    Mar 16, 2005
  2. Tibby

    Another dumb question

    Tibby, Jul 31, 2003, in forum: ASP .Net
    Replies:
    2
    Views:
    381
    Tibby
    Aug 5, 2003
  3. Cec Tre
    Replies:
    3
    Views:
    215
    Robert Klemme
    Mar 19, 2010
  4. Allen Walker

    Merging two arrays -> array of arrays

    Allen Walker, May 21, 2010, in forum: Ruby
    Replies:
    6
    Views:
    181
    Jesús Gabriel y Galán
    May 21, 2010
  5. Jerry C.
    Replies:
    8
    Views:
    279
    Uri Guttman
    Nov 23, 2003
Loading...

Share This Page