我的情况非常复杂,这就是为什么我用简单的数字替换原始数据的原因。因此,请不要注意非常简单的数据和条件是否“愚蠢”的情况。这只是一个例子。另外,请忽略拼写错误-原始代码没有拼写错误。
我有一系列带有my_hsh = {"numbers" => [1, 2, 3, 4], "n_count" => 4}
等元素的哈希值
我需要做什么:
my_arr_nochange
,the_hash["numbers"]
,my_arr_updt
。代码如下:
the_hash = {"numbers" => []}
my_arr_updt = []
my_arr_nochange = []
array_of_hashes.each do |my_hsh|
if my_hsh["n_count"] == 4
my_arr_nochange << my_hsh
updated_hsh = my_hsh
my_hsh["numbers"].each do |num|
if num == 2
the_hash["numbers"] += [ num ]
updated_hsh["numbers"] -= [ num ]
end
end
my_arr_updt << updated_hsh
end
end
return the_hash, my_arr_updt, my_arr_nochange
问题是my_arr_nochange
被修改了,所以我没有获得my_hsh的旧状态,而是得到了新状态。喜欢:
my_arr_updt
=> [{"numbers" => [1, 3, 4], "n_count" => 4}]
my_arr_nochange
=> [{"numbers" => [1, 3, 4], "n_count" => 4}]
尝试使用不同的方法并使用子变量进行拆分。没有结果。
P.S .:如果您可以帮助使用更合适的标题,我也将不胜感激。
答案 0 :(得分:6)
我相信您的问题是updated_hsh = my_hsh
。
这不会重复哈希。对updated_hsh
所做的任何更改都会更改my_hsh
,反之亦然。
使用Object#clone或Object#dup是朝正确方向迈出的一步,但实际上不会复制内部对象(“数字”数组):
h1 = [{numbers: [1,2,3], n_count: 3}]
h2 = h1.map(&:clone)
h2[0][:numbers] << 4
h2[0][:n_count] += 1
h1
# => [{numbers: [1,2,3,4], n_count: 3}]
您可以看到n_count
在原始文件中没有被更改,但是numbers
在原始文件中被更改了。
要解决此问题,您可以使用Hash#deep_dup。该方法在Ruby核心中不可用。它是Rails要求的Active Support的一部分,如果需要gem,它也可以很容易地加载到普通的Ruby程序中。
require 'active_support/all'
h1 = [{numbers: [1,2,3], n_count: 3}]
h2 = h1.map(&:deep_dup)
h2[0][:numbers] << 4
h2[0][:n_count] += 1
h1
# => [{numbers: [1,2,3], n_count: 3}]
如果您不想使用主动支持,也可以自己实现deep_dup
。参见How to create a deep copy of an object in Ruby?
另一种方法是手动构建内部哈希,如下所示:
h1 = [{numbers: [1,2,3], n_count: 3}]
h2 = h1.map do |hsh|
{
numbers: hsh[:numbers].clone,
n_count: hsh[:n_count]
}
end
尽管deep_dup
更简洁