Ruby 又有问题了,还是关于 Hash 的

galo · 2015年02月06日 · 最后由 xixiwelcome 回复于 2015年03月06日 · 2118 次阅读

代码如下 hsh1 = {a:[1, 2, 3, 4], b:[2, 4, 6, 8]} hsh2 = hsh1.dup hsh2[:a] << 5 本来预期只有 hsh2 的第一个 value 多了 5,但实际上 hsh1 和 hsh2 都被修改成了 {a:[1, 2, 3, 4, 5], b:[2, 4, 6, 8]} 看起来 hsh2 虽然是 dup 的 hsh1,但是两者的 value 还是有关联

但是当 Hash 表的 value 是字符串时,例如 hsh1 = {a:"hello ", b:"hey "} hsh2 = hsh1.dup hsh2[:a] += "ruby" 此时只有 hsh2 变成了{a:"hello ruby", b:"hey "} hsh1 还是{a:"hello ", b:"hey "} 看起来 value 是字符串时,dup 时把字符串是完全复制的,hsh1 和 hsh2 的 value 不再有关联

我想知道,当 Hash 表的 value 是什么时,dup 是完全复制的,和原件不再有关系。请大神们指点。

更新: 我已经意识到自己之前理解错了,实际上 Hash 在 dup 的时候,只是 dup 了 Hash 表本身,每个 value 都没有 dup。hsh1 和 hsh2 的 value 都是一样的,上边的例子之所以给人以错觉,是因为 hsh2[:a] += "ruby"这一行已经改变了 hsh2[:a] 的 object id,所以 hsh2[:a] 的变化没有影响到 hsh1[:a]。 看来 ruby 的 Hash 表在 dup 时,只 copy 了第一层。要想 deep copy,一楼 chenge 提供的方法可以完美的解决这个问题,谢谢。

hsh2 = Marshal.load( Marshal.dump(hsh1) )

可以 deep copy

醉心于语法不是什么好事

见图解, 第二种情况时,hsh2[:a] 最开始指导 hello 字符串,经过 += 操作后生成了一个新的字符串 hello ruby.hsh[:a] 改为指向新生成的 hello ruby. 第一种情况,hsh1,hsh2 指向共同的 array。

#2 楼 @hanluner 谢谢提醒,我有关注细节的毛病。虽然自知,但是很难改掉啊。

第二种情况,如果把+=换成<< 则结果与第一种情况一致。 因为<<是对原字符串进行操作。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号