如何阻止偏移影响数组的其他实例



我需要遍历一个数组,并保留原始数组的副本以备将来使用。

我尝试使用a = b创建另一个变量,但当我移动a时,两者都会受到影响。

rb(main):001:0> a = [1,2,3,4,5]
# => [1, 2, 3, 4, 5]
irb(main):002:0> b = a
# => [1, 2, 3, 4, 5]
irb(main):003:0> c = a.shift
# => 1
irb(main):004:0> a
# => [2, 3, 4, 5]
irb(main):005:0> b
# => [2, 3, 4, 5]
irb(main):006:0> c
# => 1

有没有办法防止这种情况发生?

在Ruby中,重要的是要记住变量是对象引用,它们的行为非常像指针,所以b = a不会复制,它是对同一对象的另一个引用。

要制作副本,您必须明确并使用dupclone来实现这一点:

b = a.dup

如果你对Ruby的行为感到困惑,停下来看看你正在处理的对象:

a = [ 1 ]
b = a
a.object_id == b.object_id
# => true

它们是完全相同的对象,但当被克隆时:

b = a.dup
a.object_id == b.object_id
# => false

现在他们是独立的,至少在高层是这样。

请注意,这附带了一些注意事项,因为这只是浅拷贝:

a = [ [ 1 ] ]
b = a.dup
b[0].object_id == a[0].object_id
# => true

如果您需要一个完整的克隆,deep_clone工具就会派上用场,它可以从各种gem中获得,但最常见的是Rails的ActiveSupport。

你会在Ruby中发现,它倾向于转向更功能性的风格,就像你想从a中剥离一个元素并避免损坏b:一样

a = [ 1, 2, 3, 4, 5 ]
b = a
a = a.drop(1)
# => [2, 3, 4, 5]

其中drop跳过前N条目,并将其余条目作为副本返回:

b
# => [1, 2, 3, 4, 5]

相关内容

最新更新