Emre
Emre

Reputation: 81

Ruby - Pushing Hash to Array

While iterating, I am saving some data to a hash each time. Within the same loop, I push the hash to an array.

The below code does not work, the last hash object overwrites all the other ones in the array.

playlists = []
aPlaylist = {}

while (count < 3)
    #some code... produces the hash "aPlaylist"
    playlist << aPlaylist
end

The code below does work. Why, and what is the difference?

playlists = []

while (count < 3)
    aPlaylist = {}
    #some code... produces the hash "aPlaylist"
    playlist << aPlaylist
end

Here are the correct and wrong outputs (converted to csv): https://i.sstatic.net/wISqj.jpg.

Upvotes: 0

Views: 195

Answers (3)

David Aldridge
David Aldridge

Reputation: 52336

I think an idiomatic Ruby approach would be something like ...

playlist = 0.upto(2).map{|count| something_that_returns_a_hash }

... or ...

playlist = (0..2).map{|count| something_that_returns_a_hash }

Hence:

0.upto(2).map{|count| {count => count} }

[{0=>0}, {1=>1}, {2=>2}] 

Upvotes: 0

guitarman
guitarman

Reputation: 3310

aPlaylist = {} creates a hash and aPlaylist variable holds a pointer to the hash object.

In your first example you edit only this one hash object.

aPlaylist = {}
count = 0
while (count < 3)
  puts aPlaylist.object_id
  count += 1
end
#=> 70179174789100
#=> 70179174789100
#=> 70179174789100

In your second example you create a new hash object within each iteration. That's way this code works.

count = 0
while (count < 3)
  aPlaylist = {}
  puts aPlaylist.object_id
  count += 1
end
#=> 70179182889040
#=> 70179182888980
#=> 70179182888920

Have a look to the printed object-ids.

Upvotes: 0

Surya
Surya

Reputation: 15992

Because, in the first case, the object is same that is on 0, 1, and 2nd index.

playlist = []
aPlaylist = {}
count = 0

while (count < 3)
    #some code... produces the hash "aPlaylist"
    playlist << aPlaylist
    puts aPlaylist.object_id
    count += 1
end
#=> 2048
#=> 2048
#=> 2048

While in second case it changes:

playlist = []

count = 0

while (count < 3)
    aPlaylist = {}
    #some code... produces the hash "aPlaylist"
    playlist << aPlaylist
    puts aPlaylist.object_id
    count += 1
end
#=> 2048
#=> 2038
#=> 2028

Which is why from second case when you make changes to hash, it does not get reflected in all places in array.

Read this stackoverflow answer for more detail.

Upvotes: 2

Related Questions