嵌套块中数组和散列的奇怪行为

时间:2015-05-29 15:22:59

标签: arrays ruby hash

我在嵌套块中使用内部数组(或散列)来保存数据:

p "#1 both inner_arr and outer_arr set empty outside of both loops"
outer_arr = []
inner_arr = []
i = 0
2.times{
  j = 0
  2.times{
    inner_arr[j] = j+100+i 
    j += 1
  }
  p inner_arr
  outer_arr[i] = inner_arr
  i += 1
  p outer_arr
}
p "======================================================"
p "#2 outer_arr set empty before both loops while inner_arr set empty inside of outer loop and outside of inner loop"
outer_arr_2 = []
i = 0
2.times{
  j = 0
  inner_arr_2 = []
  2.times{
    inner_arr_2 << j+100+i 
    j += 1
  }
  p inner_arr_2
  outer_arr_2[i] = inner_arr_2
  i += 1
  p outer_arr_2
}
p "======================================================"
p "#3 both outer and inner hash set empty outside of both loops"
outer_hash_3 = {}
inner_hash_3 = {}
i = 0
2.times{
  j = 0
  2.times{
    inner_hash_3 [j] = j+100+i 
    j += 1
  }
  p inner_hash_3
  outer_hash_3[i] = inner_hash_3
  i += 1
  p outer_hash_3
}
p "======================================================"
p "#4 outer_hash set empty before both loops while inner_hash set empty inside of outer loop and outside of inner loop"
outer_hash_4 = {}
i = 0
2.times{
  j = 0
  inner_hash_4 = {}
  2.times{
    inner_hash_4[j] = j+100+i 
    j += 1
  }
  p inner_hash_4
  outer_hash_4[i] = inner_hash_4
  i += 1
  p outer_hash_4
}

如果我在内部数组(或散列)更改时没有重置内部数组(或散列),则更新我保存在外部数组中的数据。如果我重置内部数组(或散列),那么它不会更新外部数组。我不明白为什么会这样。请帮我理解。

1 个答案:

答案 0 :(得分:1)

你在这里发现了一些东西,但我猜你还没有完全吸收它的后果。

第二种形式是正确的方法。这是因为在第一种情况下,您为每次迭代重新循环使用相同的数组,每次插入时都要反复插入相同的对象。

这在这里得到最好的证明:

a = [ 1 ]
b = [ a, a ]
# => [[1],[1]]

a << 2
# => [1,2]

b
# => [[1, 2], [1, 2]]

当您将某些内容插入到另一个结构中时,您还没有复制,您可以在技术上添加指向该数据的指针。在这种情况下,b包含指向同一a的两个指针。对a所做的任何修改都会影响b中的每个元素,但由于插入方式,元素的定义确实相同。

如果您意识到这一点,那么分配变量和向结构添加对象几乎不会导致复制,大部分时间这对您有利。如果您确实需要制作副本,dupclone等方法通常有帮助。

以更Ruby的方式重写您的简单测试,不仅可以解决问题,还可以简化问题:

(0..1).collect do |i|
  (0..1).collect do |j|
    j + 100 + i
  end
end

Ruby的可枚举库是实现这一目标的重要原因。尝试通过对数据进行一系列转换来考虑问题的解决方案。