您的问题反映了新兴 Ruby 主义者普遍存在的误解。您可以从以下内容开始:
updated_users = []
users = [{:name => "sam" , :number => 001 }]
ids = ["aa" , "bb" , "cc"]
users 是一个包含单个哈希的数组。让我们记下该哈希对象的 id:
users.first.object_id
#=> 1440
现在让我们添加一些 puts 语句来执行您的代码,看看发生了什么。
users.each do |user|
puts "user = #{user}"
puts "user.object_id = #{user.object_id}"
ids.each do |id|
puts "\nid = #{id}"
user[:guid] = id
puts "user = #{user}"
puts "user.object_id = #{user.object_id}"
updated_users << user
puts "updated_users = #{updated_users}"
updated_users.size.times do |i|
puts "updated_users[#{i}].object_id = #{updated_users[i].object_id}"
end
end
end
这将显示以下内容。
user = {:name=>"sam", :number=>1}
user.object_id = 1440
到目前为止,一切都很好。现在开始ids.each 循环:
id = aa
user = {:name=>"sam", :number=>1, :guid=>"aa"}
user.object_id = 1440
由于 user 之前没有键 :guid,因此将键值对 :guid=>"aa" 添加到 user。注意user 的 id 没有改变。然后将user 附加到(空)数组updated_users:
updated_users = [{:name=>"sam", :number=>1, :guid=>"aa"}]
updated_users[0].object_id = 1440
这也是我们应该期待的。然后处理ids 的下一个元素:
id = bb
user = {:name=>"sam", :number=>1, :guid=>"bb"}
user.object_id = 1440
由于user 有一个键:guid,这只会将该键的值从"aa" 更改为"bb"。然后将user 附加到updated_users:
updated_users = [{:name=>"sam", :number=>1, :guid=>"bb"},
{:name=>"sam", :number=>1, :guid=>"bb"}]
updated_users[0].object_id = 1440
updated_users[1].object_id = 1440
该数组的第一个和第二个元素被视为同一个对象user,因此更改:user 的键:guid 的值对这两个元素的影响相同。
在处理ids 的第三个和最后一个元素时也会发生同样的情况:
id = cc
user = {:name=>"sam", :number=>1, :guid=>"cc"}
user.object_id = 1440
updated_users = [{:name=>"sam", :number=>1, :guid=>"cc"},
{:name=>"sam", :number=>1, :guid=>"cc"},
{:name=>"sam", :number=>1, :guid=>"cc"}]
updated_users[0].object_id = 1440
updated_users[1].object_id = 1440
updated_users[2].object_id = 1440
知道了吗?
要获得您想要的结果,您需要在 updated_users 后面附加从 user 派生的不同哈希:
users.each do |user|
ids.each do |id|
updated_users << user.merge(guid: id)
end
end
updated_users
#=> [{:name=>"sam", :number=>1, :guid=>"aa"},
# {:name=>"sam", :number=>1, :guid=>"bb"},
# {:name=>"sam", :number=>1, :guid=>"cc"}]
请注意,users 尚未变异(已更改):
users
#=> [{:name=>"sam", :number=>1}]
见Hash#merge。请注意,user.merge(guid: id) 是 user.merge({ guid: id }) 的简写,或者等效地为 user.merge({ :guid => id })。