枚举期间正在修改数组

Ale*_*org 1 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
Run Code Online (Sandbox Code Playgroud)

问题正在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}]
Run Code Online (Sandbox Code Playgroud)

尝试使用不同的方法并使用子变量进行拆分。没有结果。

PS:如果您可以帮助获得更合适的标题,我也将不胜感激。

max*_*ner 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}]
Run Code Online (Sandbox Code Playgroud)

您可以看到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}]
Run Code Online (Sandbox Code Playgroud)

deep_dup如果您不想使用主动支持,也可以自己实施。请参阅如何在Ruby中创建对象的深层副本?

另一种选择是手动构建内部哈希,如下所示:

h1 = [{numbers: [1,2,3], n_count: 3}]
h2 = h1.map do |hsh|
  {
    numbers: hsh[:numbers].clone,
    n_count: hsh[:n_count]
  }
end
Run Code Online (Sandbox Code Playgroud)

虽然deep_dup更简洁