使用常量值初始化Ruby哈希

使用常量值初始化Ruby哈希,ruby,chef-infra,chef-attributes,Ruby,Chef Infra,Chef Attributes,实际上,我想在chef属性中使用这样的构造,在这里我用一个常量初始化一个结构并修改它 init_value = { "a" => { "b" => "c" } } prepare = init_value prepare["a"]["x"] = "y" 现在init_值还包含[“a”][“x”]=“y”,所以当我准备一个新值时 prepare = init_value prepare["a"]["y"] = "x" 所以prepare[“a”]包含键[“b”、“x”、“y”] 如

实际上,我想在chef属性中使用这样的构造,在这里我用一个常量初始化一个结构并修改它

init_value = { "a" => { "b" => "c" } }
prepare = init_value
prepare["a"]["x"] = "y"
现在init_值还包含
[“a”][“x”]=“y”
,所以当我准备一个新值时

prepare = init_value
prepare["a"]["y"] = "x"
所以
prepare[“a”]
包含键
[“b”、“x”、“y”]

如何使用常量初始化prepare而不引用常量,以便在最后一步中,
prepare[“a”]
仅包含两个键
[“b”,“y”]

我想在分配到prepare时,您需要init_值的“深度副本”

见:
摘自Rails 4.2.7

  • 如果对象可复制,则返回其深度副本。如果对象不可复制,则返回self

  • “返回哈希的深度副本。”

  • “返回数组的深度副本。”

实施:

class Object
  def duplicable?
    true
  end
  def deep_dup
    duplicable? ? dup : self
  end
end 

class Hash
   def deep_dup
     each_with_object(dup) do |(key, value), hash|
       hash[key.deep_dup] = value.deep_dup
     end
  end
end

class Array
  def deep_dup
    map { |it| it.deep_dup }
  end
end

# Not duplicable? 
# if ruby version < 2.0 also add Class and Module as they were not duplicable until 2.0
[Method, Symbol, FalseClass, TrueClass, NilClass, Numeric, BigDecimal].each do |m|
  m.send(:define_method, :duplicable?, ->{false})
end
和用法

prepare = init_value
prepare["a"]["x"] = "y"

prepare2 = init_value
prepare2["a"]["y"] = "x"

prepare
#=> {"a"=>{"b"=>"c", "x"=>"y"}}
prepare2
#=> {"a"=>{"b"=>"c", "y"=>"x"}}

您可以将初始哈希移动到方法中。这样,该方法总是返回一个“新鲜”散列:


请举例说明如何做,然后我将投票支持你的答案。事实上,你所引用的答案并没有包含有用的例子。我给出了一个简单的例子,可以很容易地转换为代码驱动的答案,因为Ruby实际上似乎缺少真正的深度复制功能。似乎唯一实用的方法是
prepare=Marshal.load(Marshal.dump(init_value))
。我甚至都不会称这本书为副本。ruby似乎完全没有用于哈希的真正的“深度复制”函数。如果你知道一个方法,请提出一个!不幸的是,封送是进行深度复制的方法。因为即使是
dup
freeze
也不会停止对值本身的修改,只会分配给键。这看起来是一个合理的答案。明天我将尝试并批准它是否适合我。@Ikrabe取决于您的实现签出Stefan的答案,因为它提供了相同的功能,没有任何代码。话虽如此,我还是把这篇文章作为“深度复制”的一个例子,因为它似乎是这篇文章中的一个热门话题。这是迄今为止最简单的解决方案(我不敢相信我忽略了这一点),我非常关注这样一个事实,以至于OP和其他评论者似乎都认为深度复制是不受支持的。谢谢大家!我想我们真的找到了我一直在寻找的东西,可能还有更多!良好的团队合作@engineersmnky
prepare = init_value
prepare["a"]["x"] = "y"

prepare2 = init_value
prepare2["a"]["y"] = "x"

prepare
#=> {"a"=>{"b"=>"c", "x"=>"y"}}
prepare2
#=> {"a"=>{"b"=>"c", "y"=>"x"}}
def init_value
  {"a"=>{"b"=>"c"}}
end

prepare = init_value
prepare["a"]["x"] = "y"
prepare
#=> {"a"=>{"b"=>"c", "x"=>"y"}}

prepare = init_value
prepare["a"]["y"] = "x"
prepare
#=> {"a"=>{"b"=>"c", "y"=>"x"}}