简体   繁体   中英

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): http://imgur.com/a/rjmBA .

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.

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.

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}] 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM