3

我有以下代码:

default = {:id => 0, :detail =>{:name=>"Default", :id => ""}}
employees = {}

nr = (0..3).to_a 
nr.each do |n|
    employee = default
    employee[:id] = n
    employee[:detail][:name] = "Default #{n}"
    employee[:detail][:id] = "KEY-#{n}"
    employees[n] = employee
end
puts employees

我希望散列中键:id的值是, , 。:detailKEY-0KEY-1KEY-2

4

3 回答 3

1

你只需要改变:

default = { :id=>0, :detail=>{ :name=>"Default", :id=>"" } }

def default
  {}.merge(:id=>0, :detail=>({}.merge(:name=>"Default", :id=>"")))
end

但是,嘿,当我们这样做的时候,我们不妨对其余的部分进行 Ruby 化:

employees = (0..3).map do |n|
    employee = default
    employee[:id] = n
    employee[:detail][:name] = "Default #{n}"
    employee[:detail][:id] = "KEY-#{n}"
    employee
end
  #=> [{:id=>0, :detail=>{:name=>"Default 0", :id=>"KEY-0"}},
  #    {:id=>1, :detail=>{:name=>"Default 1", :id=>"KEY-1"}},
  #    {:id=>2, :detail=>{:name=>"Default 2", :id=>"KEY-2"}},
  #    {:id=>3, :detail=>{:name=>"Default 3", :id=>"KEY-3"}}] 

让我们确认我们正在制作以下内容的深层副本default

employees[0][:detail][:id] = "cat"
employees
  #=> [{:id=>0, :detail=>{:name=>"Default 0", :id=>"cat"}},
  #    {:id=>1, :detail=>{:name=>"Default 1", :id=>"KEY-1"}},
  #    {:id=>2, :detail=>{:name=>"Default 2", :id=>"KEY-2"}},
  #    {:id=>3, :detail=>{:name=>"Default 3", :id=>"KEY-3"}}] 

你会更常见地看到这样写:

employees = (0..3).map do |n|
  default.merge(:id=>n, :detail=>{:name=>"Default #{n}", :id=>"KEY-#{n}"})
end
  #=> [{:id=>0, :detail=>{:name=>"Default 0", :id=>"cat"}},
  #    {:id=>1, :detail=>{:name=>"Default 1", :id=>"KEY-1"}},
  #    {:id=>2, :detail=>{:name=>"Default 2", :id=>"KEY-2"}},
  #    {:id=>3, :detail=>{:name=>"Default 3", :id=>"KEY-3"}}] 

正如其他答案所建议的那样,您可以这样做:

class Object
  def deep_copy
    Marshal.load(Marshal.dump(self))
  end
end

然后你可以写:

default = { :id=>0, :detail=>{ :name=>"Default", :id=>"" } }
employees = (0..3).map do |n|
  default.deep_copy.merge(:id=>n, :detail=>{:name=>"Default #{n}",
    :id=>"KEY-#{n}"})
end
  #=> [{:id=>0, :detail=>{:name=>"Default 0", :id=>"KEY-0"}},
  #    {:id=>1, :detail=>{:name=>"Default 1", :id=>"KEY-1"}},
  #    {:id=>2, :detail=>{:name=>"Default 2", :id=>"KEY-2"}},
  #    {:id=>3, :detail=>{:name=>"Default 3", :id=>"KEY-3"}}] 

这样做的好处是,如果您更改default,则不需要其他更改。

于 2015-07-17T05:03:41.303 回答
1

您需要整理您的默认值才能复制

default = {id: 0, detail: {name: "Default", id:""}}
employees = {}
4.times do |n|
  employees[n] = Marshal.load(Marshal.dump(default))
  employees[n][:id] = n
  employees[n][:detail][:name] = "Default #{n}"
  employees[n][:detail][:id] = "KEY-#{n}"
end
puts employees

输出是

{0=>{:id=>0, :detail=>{:name=>"Default 0", :id=>"KEY-0"}}, 1=>{:id=>1, :detail=>{:name=>"Default 1", :id=>"KEY-1"}}, 2=>{:id=>2, :detail=>{:name=>"Default 2", :id=>"KEY-2"}}, 3=>{:id=>3, :detail=>{:name=>"Default 3", :id=>"KEY-3"}}}

您可以阅读这篇文章Cloning an array with its content

添加

在这里,您有一个减少版本,如果您愿意,应该更快。

employees = {}
4.times { |n| employees[n]={id: n, detail: {name: "Default #{n}", id:"KEY-#{n}"}} }
puts employees
于 2015-07-16T22:05:26.903 回答
0

您在每次迭代中制作浅拷贝,即每次使用上次迭代中计算的值覆盖每个拷贝。您可以为您的 hash-within-hash 默认模式尝试以下操作以进行深层复制:

employee = Marshal.load(Marshal.dump(default))

示范

于 2015-07-16T21:47:27.850 回答