枚举期间正在修改数组

时间:2019-07-01 18:18:45

标签: ruby variables

我的情况非常复杂,这就是为什么我用简单的数字替换原始数据的原因。因此,请不要注意非常简单的数据和条件是否“愚蠢”的情况。这只是一个例子。另外,请忽略拼写错误-原始代码没有拼写错误。

我有一系列带有my_hsh = {"numbers" => [1, 2, 3, 4], "n_count" => 4}等元素的哈希值

我需要做什么:

  1. 遍历父数组并选择适当的哈希,
  2. 将每个这样的哈希添加到数组my_arr_nochange
  3. 在每个这样的哈希中遍历“数字”,并将它们添加到the_hash["numbers"]
  4. 将没有这些数字的哈希添加到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 .:如果您可以帮助使用更合适的标题,我也将不胜感激。

1 个答案:

答案 0 :(得分:6)

我相信您的问题是updated_hsh = my_hsh

这不会重复哈希。对updated_hsh所做的任何更改都会更改my_hsh,反之亦然。

使用Object#cloneObject#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更简洁