是什么导致了这里的问题?

当我在 ruby​​ 中运行此代码时:

updated_users = []
users = [{:name => "sam" , :number => 001 }]
ids = ["aa" , "bb" , "cc"]
 
users.each do |user|
  ids.each do |id|
    user[:guid] = id
    updated_users << user
  end       
end

p updated_users

我得到:

[{:name=>"sam", :number=>1, :guid=>"cc"},
 {:name=>"sam", :number=>1, :guid=>"cc"},
 {:name=>"sam", :number=>1, :guid=>"cc"}]

我希望得到:

[{:name=>"sam", :number=>1, :guid=>"aa"},
 {:name=>"sam", :number=>1, :guid=>"bb"},
 {:name=>"sam", :number=>1, :guid=>"cc"}]

发生了什么,我应该如何获得所需的输出?

回答

您的问题反映了初露头角的 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之前没有 key :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 })


以上是是什么导致了这里的问题?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>