Forum: Ruby Appending to an Array

B042e8df4e54aa3cfd2990a65a58b80b?d=identicon&s=25 Anthony Simonelli (Guest)
on 2012-02-07 22:28
(Received via mailing list)
I am querying a database using DBI and ODBC.  After I run the execute, I
want to grab each row as an array, and add it to another array,
essentially
creating an Array of Arrays.  I've tried this two ways with the same
result:

sth = dbh.execute("SELECT * FROM SOMETABLE")
rows = sth.fetch_all

and

rows = sth.fetch do |row|
    rows << row
end

The result for both is that the last row is repeated in the array
however
many times there are rows.  Why isn't it appending correctly?

Thanks,

Anthony
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (robert_k78)
on 2012-02-07 23:05
(Received via mailing list)
On Tue, Feb 7, 2012 at 10:27 PM, Anthony Simonelli
<asimonelli01@gmail.com> wrote:
>  rows << row
> end
>
> The result for both is that the last row is repeated in the array however
> many times there are rows. Why isn't it appending correctly?

Probably because the DB driver optimizes object allocation and reuses
the same instance.  Then this is what happens:

irb(main):006:0> rows = []
=> []
irb(main):007:0> a = %w{a b c d}
=> ["a", "b", "c", "d"]
irb(main):008:0> rows << a
=> [["a", "b", "c", "d"]]
irb(main):009:0> a[2] = 99
=> 99
irb(main):010:0> rows << a
=> [["a", "b", 99, "d"], ["a", "b", 99, "d"]]

The phenomenon is called "aliasing".

You can solve it by copying row Arrays.

rows = []

sth.fetch do |row|
  rows << row.to_a # if rows is not an Array
  rows << row.dup # if rows is an Array
end

Kind regards

robert
160992dfd434ff7055465446b9423bd5?d=identicon&s=25 Peter Vandenabeele (petervandenabeele)
on 2012-02-07 23:23
(Received via mailing list)
On Tue, Feb 7, 2012 at 11:04 PM, Robert Klemme
<shortcutter@googlemail.com>wrote:

> >
> the same instance.  Then this is what happens:
> => [["a", "b", 99, "d"], ["a", "b", 99, "d"]]
> end
>

Would `Array(row)` not be a clean implementation of this ?

peterv@ASUS:~$ irb
001:0> row = "a string"
=> "a string"
002:0> Array(row)
=> ["a string"]
003:0> row = [:array_entry]
=> [:array_entry]
004:0> Array(row)
=> [:array_entry]

Peter
E0d864d9677f3c1482a20152b7cac0e2?d=identicon&s=25 Robert Klemme (robert_k78)
on 2012-02-08 09:52
(Received via mailing list)
On Tue, Feb 7, 2012 at 11:22 PM, Peter Vandenabeele
<peter@vandenabeele.com> wrote:
>> >
>> > many times there are rows. Why isn't it appending correctly?
>> irb(main):009:0> a[2] = 99
>> sth.fetch do |row|
> 002:0> Array(row)
> => ["a string"]
> 003:0> row = [:array_entry]
> => [:array_entry]
> 004:0> Array(row)
> => [:array_entry]

Judge for yourself:

irb(main):001:0> a = [:x]
=> [:x]
irb(main):002:0> b = Array(a)
=> [:x]
irb(main):003:0> b.equal? a
=> true
irb(main):004:0> a.object_id == b.object_id
=> true

Kind regards

robert
Please log in before posting. Registration is free and takes only a minute.
Existing account

NEW: Do you have a Google/GoogleMail, Yahoo or Facebook account? No registration required!
Log in with Google account | Log in with Yahoo account | Log in with Facebook account
No account? Register here.