将散列常量克隆到新变量中,而不在使用 .each 块更新时改变常量?
Clone constant of hash into new variable without mutating constant on update with .each block?
我正在为某事而苦苦挣扎。我已经将我的代码抽象得尽可能简单,但我仍然不明白为什么它会出现这种行为。
我正在创建一个由一组键值对组成的常量并将其冻结。然后我使用 .dup 方法将散列复制到一个新变量中。
但是,当我遍历一个数组并尝试将其存储在新变量中的(以前为空的)数组中时,它不仅更新了新变量,还更新了原始常量。这似乎只是 .each 方法的情况 - 如果我直接将新值作为新数组传递,它可以在不更新常量的情况下工作。
我的抽象代码如下:
CONFIG_VALUES = { results: [], loop_count: 0 }.freeze
the_results = ["foo", "bar"]
abc = CONFIG_VALUES.dup
the_results.each do |res|
abc[:results] << res
end
abc
#=> {:results=>["foo", "bar"], :loop_count=>0}
CONFIG_VALUES
#=> {:results=>["foo", "bar"], :loop_count=>0}
Hash#dup
方法不是递归的。无论如何,如果你在 Rails 上使用 Ruby,并且我认为你在标记它后就这样做了,你可以使用 #deep_dup
方法:http://api.rubyonrails.org/classes/Hash.html#method-i-deep_dup
这是一种 ActiveSupport 方法,因此如果您不在 Rails 上使用 Ruby,您可以只使用 gem。
您可以通过以下方式获得所需的结果:
CONFIG_VALUES = { results: [], loop_count: 0 }.freeze
the_results = %w[foo bar]
abc = CONFIG_VALUES.merge(results: the_results)
abc
#=> {:results=>["foo", "bar"], :loop_count=>0}
CONFIG_VALUES
#=> {:results=>[], :loop_count=>0}
据我了解,这是可行的,因为 #merge
不会发生变化 CONFIG_VALUES
并且您实际上是在创建一组全新的对象。
我正在为某事而苦苦挣扎。我已经将我的代码抽象得尽可能简单,但我仍然不明白为什么它会出现这种行为。
我正在创建一个由一组键值对组成的常量并将其冻结。然后我使用 .dup 方法将散列复制到一个新变量中。
但是,当我遍历一个数组并尝试将其存储在新变量中的(以前为空的)数组中时,它不仅更新了新变量,还更新了原始常量。这似乎只是 .each 方法的情况 - 如果我直接将新值作为新数组传递,它可以在不更新常量的情况下工作。
我的抽象代码如下:
CONFIG_VALUES = { results: [], loop_count: 0 }.freeze
the_results = ["foo", "bar"]
abc = CONFIG_VALUES.dup
the_results.each do |res|
abc[:results] << res
end
abc
#=> {:results=>["foo", "bar"], :loop_count=>0}
CONFIG_VALUES
#=> {:results=>["foo", "bar"], :loop_count=>0}
Hash#dup
方法不是递归的。无论如何,如果你在 Rails 上使用 Ruby,并且我认为你在标记它后就这样做了,你可以使用 #deep_dup
方法:http://api.rubyonrails.org/classes/Hash.html#method-i-deep_dup
这是一种 ActiveSupport 方法,因此如果您不在 Rails 上使用 Ruby,您可以只使用 gem。
您可以通过以下方式获得所需的结果:
CONFIG_VALUES = { results: [], loop_count: 0 }.freeze
the_results = %w[foo bar]
abc = CONFIG_VALUES.merge(results: the_results)
abc
#=> {:results=>["foo", "bar"], :loop_count=>0}
CONFIG_VALUES
#=> {:results=>[], :loop_count=>0}
据我了解,这是可行的,因为 #merge
不会发生变化 CONFIG_VALUES
并且您实际上是在创建一组全新的对象。