2

例如:

a = [1,2,3,4]
b = a
c = a.to_a
a.insert(0,0)  #=> [0,1,2,3,4]
b              #=> [0,1,2,3,4]
c              #=> [0,1,2,3,4]

为什么数组的输出b和输出c是一样的?如果我想获得 array 的副本a,而不是参考副本,我应该使用哪种方法?

4

5 回答 5

4

为什么数组 b 和 c 的输出是一样的?

因为所有三个局部变量都引用了相同的对象,如下所示:

a = [1,2,3,4]
b = a
c = a.to_a
a.object_id
# => 72187200
b.object_id
# => 72187200
c.object_id
# => 72187200

如果我想获取数组 a 的副本,而不是参考,我应该使用哪种方法?

然后使用a.dup.Here 记录Object#dup

a = [1,2,3,4]
b = a.dup
c = a.dup
a.object_id
# => 82139270
b.object_id
# => 82139210
c.object_id
# => 82134600
a.insert(0,0) # => [0, 1, 2, 3, 4]
b # => [1, 2, 3, 4]
c # => [1, 2, 3, 4]

Array#to_a说:返回自我。如果在 Array 的子类上调用,则将接收者转换为 Array 对象。

因此,根据您的需要,它不会有帮助。

于 2013-08-10T14:57:27.290 回答
2

这是因为Array#to_a返回self,所以两个变量都包含对同一个 Array 对象的引用。为了获得具有相同内容的新数组,您可以使用dupclone(阅读之间的区别dupclone):

a = [1, 2, 3]
b = a.dup
a << 4
a  #=> [1, 2, 3, 4]
b  #=> [1, 2, 3]

但是请注意,相同的对象引用存储在新数组中。这意味着如果你改变对象本身,它们仍然会在两个数组中发生变化:

a = ['foo', 'bar']
b = a.dup
a[0] << 'baz'
a  #=> ["foobaz", "bar"]
b  #=> ["foobaz", "bar"]

这是因为dupclone浅拷贝

于 2013-08-10T15:04:35.933 回答
1

Array#to_a返回接收器。这就是为什么bc指的是同一件事。关于为什么to_a返回原始数组,原则上,它可以以一种或另一种方式定义,但我想一个用例to_a是将它应用于可能nil确保它成为数组的变量。

some_value.to_a # => `[]` if `some_value` is `nil`

在这种用例中,如果接收器已经是一个数组,则无需将数组替换为另一个数组。这在性能上会更可取。

于 2013-08-10T15:05:51.440 回答
1

原因是变量只是对数据的引用。变量存储在内存中;变量保存它们在内存中所在位置的地址。所以当你这样做时:

a = b

这两个变量指向同一个内存位置,因此如果你 alter ab也会被改变,因为它是同一个对象。

有几种方法可以强制 Ruby 创建对象的另一个副本。最流行的是dupLBg提到的方法。但是请注意,它只是创建一个浅拷贝。如果你运行:

a = ['foo','bar', []]
b = a.dup

a << 'blah'
b              #=> ['foo', 'bar', []] as expected but

b[3] << blah

a              #=> ['foobar', 'bar', ['blah]]

原因是数组实际上是一个引用数组,嵌套数组在执行时没有重复dup,所以它们是同一个对象。

要创建对象的深层副本,您可以使用 Marshall 模块:

b = Marshal.load(Marshal.dump(a))

但是,通常您实际上并不需要这样做。此外,某些对象不能被复制(例如符号)。

于 2013-08-10T15:10:04.063 回答
0

你可以做

b = a.dup

旧帖子
如果没有更简单的方法,你可以试试这个

b = a.map {|x| x}

有用

1.9.3-p448 :001 > a = [1,2,3]      => [1, 2, 3] 
1.9.3-p448 :002 > b = a            => [1, 2, 3] 
1.9.3-p448 :003 > c = a.map{|x| x} => [1, 2, 3] 
1.9.3-p448 :004 > a<<0             => [1, 2, 3, 0] 
1.9.3-p448 :005 > b                => [1, 2, 3, 0] 
1.9.3-p448 :006 > c                => [1, 2, 3] 

但它是一个浅拷贝。

根据这篇文章a.dup是更简单的方法。

于 2013-08-10T14:51:25.913 回答