weird behavior pushing an array onto an array

Discussion in 'Ruby' started by eagle eyes joe, Sep 28, 2004.

  1. Greetings,

    In my program, I fill an array, a, with data and push it onto an array b
    which is initially empty. At each iteration, all the previous pushed
    values become the same as the last item, so I end up with an array of
    many copies of the last item.

    Can you please help?


    Joe.






    (rdb:1) c
    ACFFX 25.01 15.13 3.25 0 1.45 0
    Breakpoint 1, toplevel at funds:65
    funds:66: a.fill(0)
    (rdb:1) p a
    ["ACFFX", "25.01", "15.13", "3.25", 0, "1.45", 0]
    (rdb:1) p b
    [["ACFFX", "25.01", "15.13", "3.25", 0, "1.45", 0], ["ACFFX", "25.01",
    "15.13", "3.25", 0, "1.45", 0], ["ACFFX", "25.01", "15.13", "3.25", 0,
    "1.45", 0], ["ACFFX", "25.01", "15.13", "3.25", 0, "1.45", 0]]
    (rdb:1) c
    ACINX 28.53 15.63 3.95 7.76 1.05 0
    Breakpoint 1, toplevel at funds:65
    funds:65: b.push(a)
    (rdb:1) p a
    ["ACINX", "28.53", "15.63", "3.95", "7.76", "1.05", 0]
    (rdb:1) p b
    [["ACINX", "28.53", "15.63", "3.95", "7.76", "1.05", 0], ["ACINX",
    "28.53", "15.63", "3.95", "7.76", "1.05", 0], ["ACINX", "28.53",
    "15.63", "3.95", "7.76", "1.05", 0], ["ACINX", "28.53", "15.63", "3.95",
    "7.76", "1.05", 0]]
    (rdb:1) exit
    [Abba:~/ruby] josephal% cat funds
    #!/usr/bin/ruby

    ....

    a = Array.new(7, 0) # a is the line item
    b = Array.new # b is the array of arrays
    ....

    r.each do |i|
    ...
    b.push(a)
    ...
    end
    eagle eyes joe, Sep 28, 2004
    #1
    1. Advertising

  2. eagle eyes joe wrote:

    > Greetings,


    Moin.

    > In my program, I fill an array, a, with data and push it onto an array b
    > which is initially empty.


    You push the same array over and over. You want to push a copy instead.
    Use #clone or #dup to get a copy of the Array.

    Regards,
    Florian Gross
    Florian Gross, Sep 28, 2004
    #2
    1. Advertising

  3. > > In my program, I fill an array, a, with data and push it onto an array b
    > > which is initially empty.

    >
    > You push the same array over and over. You want to push a copy instead.
    > Use #clone or #dup to get a copy of the Array.


    Beware that may not be enough by itself, because the array contains strings;
    even if you dup the array you will still have references to the same
    strings. This will become apparent if you later modify one of the strings:

    a = ["one","two","three"]
    b = []
    b << a.dup << a.dup
    b[0][0] << "XXX"
    p b
    # => [["oneXXX", "two", "three"], ["oneXXX", "two", "three"]]

    But it's not an issue if you only ever replace the array elements with a
    reference to another object, e.g.

    b[0][0] = "newstring"

    A safer way is to fill the array directly:

    b = []
    5.times do
    b << ["ACINX", "28.53", "15.63", "3.95", "7.76", "1.05", 0]
    end

    Or more compactly,

    b = (1..5).collect { ["ACINX", "28.53", "15.63", "3.95", "7.76", "1.05", 0] }

    That's because each time a constant like "ACINX" is executed, it creates a
    brand new String object; equally, each time [ ... ] is executed it creates a
    brand new Array object.

    Alternatively, you can do a "deep copy" of the array and its contents. A
    quick and fairly convenient way to do this is with Marshal, to serialise the
    object and then create a fresh object tree from the serialised form.

    a = ["one","two","three"]
    b = []
    b << Marshal.load(Marshal.dump(a)) << Marshal.load(Marshal.dump(a))
    b[0][0] << "XXX"
    p b
    # => [["oneXXX", "two", "three"], ["one", "two", "three"]]

    Regards,

    Brian.
    Brian Candler, Sep 28, 2004
    #3
  4. Brian Candler wrote:

    >>>In my program, I fill an array, a, with data and push it onto an array b
    >>>which is initially empty.

    >>You push the same array over and over. You want to push a copy instead.
    >>Use #clone or #dup to get a copy of the Array.

    > Beware that may not be enough by itself, because the array contains strings;
    > even if you dup the array you will still have references to the same
    > strings. This will become apparent if you later modify one of the strings:


    Thank you for the correction, you are right of course.

    > Or more compactly,
    >
    > b = (1..5).collect { ["ACINX", "28.53", "15.63", "3.95", "7.76", "1.05", 0] }


    Or even this:

    b = Array.new(5) { ["ACINX", "28.53", "15.63", "3.95", "7.76", "1.05", 0] }

    > Regards,
    > Brian.


    More regards,
    Florian Gross
    Florian Gross, Sep 28, 2004
    #4
    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. Timo
    Replies:
    1
    Views:
    585
    Karl Seguin
    Mar 3, 2005
  2. Dave
    Replies:
    2
    Views:
    404
    Jim Langston
    Aug 15, 2007
  3. Prasanth
    Replies:
    4
    Views:
    407
    Prasanth
    Nov 22, 2008
  4. Jon Hawkins
    Replies:
    2
    Views:
    111
    Robert Klemme
    Aug 3, 2007
  5. Replies:
    4
    Views:
    90
    Tad McClellan
    Mar 15, 2006
Loading...

Share This Page