Arrays 为什么将一个值附加到散列中的数组也会修改分配了它的其他变量?

Arrays 为什么将一个值附加到散列中的数组也会修改分配了它的其他变量?,arrays,ruby,hash,Arrays,Ruby,Hash,示例代码: hash_of_array = { a: [] } b = hash_of_array c = hash_of_array b[:a] << 1 puts b # => { a: [1] } puts c # => { a: [1] } 为什么两个变量的数组中都有1?我只把它附加在变量b上 试穿 Ruby版本2.3.1、2.4.0 Rbenv 因为b的值和c的值是同一个对象签出: 因为b的值和c的值是同一个对象签出: ruby中的所有对象都是通过引用分配

示例代码:

hash_of_array = { a: [] }
b = hash_of_array
c = hash_of_array

b[:a] << 1

puts b # => { a: [1] }
puts c # => { a: [1] }
为什么两个变量的数组中都有1?我只把它附加在变量b上

试穿

Ruby版本2.3.1、2.4.0 Rbenv 因为b的值和c的值是同一个对象签出:

因为b的值和c的值是同一个对象签出:


ruby中的所有对象都是通过引用分配的,除了True、False、Nil和Fixnums,它们都是专门处理的

您可以通过查看对象id来测试它

要创建对象的副本,请使用.dup

例如,您需要一个深度副本,这样您就可以

Marshal.load(Marshal.dump(hash))
所以


ruby中的所有对象都是通过引用分配的,除了True、False、Nil和Fixnums,它们都是专门处理的

您可以通过查看对象id来测试它

要创建对象的副本,请使用.dup

例如,您需要一个深度副本,这样您就可以

Marshal.load(Marshal.dump(hash))
所以


正如前面提到的,非常好的答案,你面临的问题是a和b是同一个对象。另一个答案后来被删除,建议使用dup方法,如果浅拷贝就足够了。问题是,在您的场景中,浅拷贝是不够好的

我建议试试全套的宝石。这个gem添加了一个新方法,称为full_dup。完整复制会对对象进行深度复制。举个例子:

require 'full_dup'

hash_of_array = { a: [] }
b = hash_of_array.full_dup
c = hash_of_array.full_dup

b[:a] << 1

puts b # => { a: [1] }
puts c # => { a: [] }
顺便说一句,full_dup不是速度恶魔。当您只需要使用常规dup时,应该使用该方法


哎呀,;忘了提了。我是《完整的宝石》的作者。

正如前面的优秀答案所提到的,你面临的问题是a和b是同一个物体。另一个答案后来被删除,建议使用dup方法,如果浅拷贝就足够了。问题是,在您的场景中,浅拷贝是不够好的

我建议试试全套的宝石。这个gem添加了一个新方法,称为full_dup。完整复制会对对象进行深度复制。举个例子:

require 'full_dup'

hash_of_array = { a: [] }
b = hash_of_array.full_dup
c = hash_of_array.full_dup

b[:a] << 1

puts b # => { a: [1] }
puts c # => { a: [] }
顺便说一句,full_dup不是速度恶魔。当您只需要使用常规dup时,应该使用该方法


哎呀,;忘了提了。我是《完整的宝石》的作者。

我认识一个叫约翰的人。有人叫他约翰尼。约翰尼今天中枪了。为什么约翰也被枪杀了


简单地给_something uo取另一个名字foo。它不会克隆它或做任何其他恶作剧

我认识一个叫约翰的人。有人叫他约翰尼。约翰尼今天中枪了。为什么约翰也被枪杀了


简单地给_something uo取另一个名字foo。它不会克隆它或做任何其他恶作剧

在您的示例中,如所述,b和c基本上是同一个对象

不过,你不必表现出你所困惑的行为

重要的是它们持有对同一数组的引用:

array = []

b = { b: array }
c = { c: array }

puts b == c
#=> false

puts b.object_id == c.object_id
#=> false

puts b[:b].object_id == c[:c].object_id
#=> true

b[:b] << 'test'

p b
# {:b=>["test"]}
p c
# {:c=>["test"]}

在您的示例中,正如所提到的,b和c基本上是相同的对象

不过,你不必表现出你所困惑的行为

重要的是它们持有对同一数组的引用:

array = []

b = { b: array }
c = { c: array }

puts b == c
#=> false

puts b.object_id == c.object_id
#=> false

puts b[:b].object_id == c[:c].object_id
#=> true

b[:b] << 'test'

p b
# {:b=>["test"]}
p c
# {:c=>["test"]}

在OP的示例中如何使用dup?您需要Rails deep_dup在OP的示例中如何使用dup?您需要Rails deep_dup推荐您自己的库是可以的,但您必须公开您的从属关系。为什么.dup不够?full_dup做了什么使它适合这里?当您需要常规dup时,您应该使用该方法。-这是什么时候?dup方法执行浅拷贝。full_dup方法执行深度复制。浅拷贝比深拷贝快,但它们。。。浅的我的回答中都提到了这一点。我可以补充一点,浅层副本会复制容器对象,但不会复制其内容。深度副本也会根据需要复制容器对象及其内容及其内容等。正如可以预料的那样,这需要相当长的时间,如果不需要,应该避免。什么时候需要?你需要弄清楚这一点并进行判断。推荐你自己的图书馆是可以的,但你必须公开你的隶属关系。为什么.dup不够?full_dup做了什么使它适合这里?当您需要常规dup时,您应该使用该方法。-这是什么时候?dup方法执行浅拷贝。full_dup方法执行深度复制。浅拷贝比深拷贝快,但它们。。。浅的我的回答中都提到了这一点。我可以补充一点,浅层副本会复制容器对象,但不会复制其内容。深度副本也会根据需要复制容器对象及其内容及其内容等。正如可以预料的那样,这需要相当长的时间,如果不需要,应该避免。什么时候需要?你需要弄清楚这一点,并做出判断。我很难处理绞刑架上的幽默,因为我的兄弟约翰也死了。这看起来不像一个情节
“对我来说,答案是肯定的,但这是可以接受的。”@bekicot,C中的作业也会以同样的方式进行。在更高的层次上思考一下-=只说出右边的东西。我们能找到一个更符合Ruby程序员快乐价值而不是杀人价值的例子吗?也许约翰反而中了彩票?@ndn我比你高,因为这给了我一种新的心态。谢谢。我弟弟约翰也死了,所以我很难处理绞刑架上的幽默。这看起来不像是指向我的指针,但这是可以接受的答案。@bekicot,C中的作业也会以同样的方式进行。在更高的层次上思考一下-=只说出右边的东西。我们能找到一个更符合Ruby程序员快乐价值而不是杀人价值的例子吗?也许约翰反而中了彩票?@ndn我比你高,因为这给了我一种新的心态。谢谢
foo = _something_
array = []

b = { b: array }
c = { c: array }

puts b == c
#=> false

puts b.object_id == c.object_id
#=> false

puts b[:b].object_id == c[:c].object_id
#=> true

b[:b] << 'test'

p b
# {:b=>["test"]}
p c
# {:c=>["test"]}