【问题标题】:Cloning an array with its content克隆数组及其内容
【发布时间】:2021-09-01 12:52:10
【问题描述】:

我想复制一个数组,在原地修改副本,而不影响原来的。此代码失败

a = [
  '462664',
  '669722',
  '297288',
  '796928',
  '584497',
  '357431'
]
b = a.clone
b.object_id == a.object_id # => false
a[1][2] = 'X'
a[1] #66X722
b[1] #66X722

副本应该与对象不同。为什么它只是一个参考?

【问题讨论】:

  • 如果您使用检查方法,它们是两个不同的对象,它应该显示不同的内存分配值。克隆会复制变量,但不会复制它们引用的对象。

标签: ruby object copy clone


【解决方案1】:

你需要对你的数组做一个深拷贝。

方法如下

Marshal.load(Marshal.dump(a))

这是因为您正在克隆数组而不是其中的元素。所以数组对象是不同的,但它包含的元素是相同的实例。例如,你也可以为你的情况做a.each{|e| b << e.dup}

【讨论】:

  • 谢谢,我会用它,但我认为只有符号引用同一个对象,为什么字符串 a[1] 和 b[1] 引用同一个对象?
  • 很好!!!我已经尝试过 dup、clone 和 Array.new(a) 并且仍然对其进行了更改,我认为 ruby​​ 创建了一个包含指向每个值的指针的数组。
  • 在 Ruby 中,一切都是对象,因此数组包含对字符串的引用,而不是字符串本身。克隆数组时,引用会被复制,但副本会一直指向原始字符串。
  • @RedouaneRed 字符串a[1] b[1] 相同的对象。我不确定我是否理解您对符号的担忧,因为符号是不可变的
  • 我的意思是当你创建 2 个相似的字符串时,你会创建 2 个对象,但是当你创建 2 个相似的符号时,你只会创建 1 个,感谢@NicNilov 的解释。
【解决方案2】:

不确定,如果在其他任何地方都回答了这个问题。尝试搜索但没有成功。

试试这个

current_array =["a", "b","c","d"]
new_array = current_array[0 .. current_array.length]
new_array[0] ="cool"

output of new_array
 "cool","b","c","d"

希望这会有所帮助。

【讨论】:

  • 该解决方案有效。不确定是否有人已经回答了这个问题,因为它可能已经逃脱了我的搜索工作,因为搜索后找不到解决方案,如果已经回答,不想重复。希望这会有所帮助。
  • 你错过了这里的窍门。您需要更改其中一个数组并检查此更改是否反映到另一个数组。
【解决方案3】:

试试这个:

b = [] #create a new array 
b.replace(a) #replace the content of array b with the content from array a

此时,这两个数组是对不同对象的引用,内容相同。

【讨论】:

  • 这也不能做深度复制...试试a = [[1, 2, [3, 4]]]
  • Sundeep 说的:如果你这样做replace 方法而不是问题中发布的clone 方法,你会得到完全相同的结果。因此,这只是与 OP 所做的相同事情的不同方式(而他显然在寻找不同的结果)。
【解决方案4】:

您可以使用map 在数组的每个元素上调用它,而不是在数组本身上调用clone

b = a.map(&:clone)

这在问题中所述的示例中有效,因为您会为数组中的每个元素获得一个新实例。

【讨论】:

  • 这仍然不是 deepcopy.. 例如:a = [[1, 2, [3, 4]]]; b = a.map(&:clone); a[0][2][0] = 'foo' 也会更改 b
  • @Sundeep 这个问题是关于一个简单的对象数组,所以不需要深拷贝。如果您希望更详细地讨论新示例,可以将新示例作为单独的问题发布到 Stack Overflow。
  • 是的,对于给定的示例,这是可行的。我应该提到我的评论为 fyi/note.. 并不是说​​答案是错误的..
  • 确实,如果您使用 map(&:clone) 方法而不是问题中发布的 clone 方法,这将给出 OP 正在寻找的结果。所以确实是一个有效的答案。
【解决方案5】:

您可以使用#dup 创建对象的浅表副本,这意味着“对象的实例变量被复制,而不是它们引用的对象。” 例如:

a = [1, 2, 3]

b = a.dup

b # => [1, 2, 3]

来源:https://ruby-doc.org/core-2.5.3/Object.html#method-i-dup

编辑:听我下面的保罗。我误解了这个问题。

【讨论】:

  • -1 对于这个问题 dupclone 产生与 OP 得到的完全相同的结果,所以并不是这个问题的真正答案。对于那些现在对dupclone 之间的区别感到好奇的人,请参阅stackoverflow.com/questions/10183370/…
【解决方案6】:

您可以只映射数组的元素。我相信这是迄今为止最干净的解决方案。

array.map(&:itself)

【讨论】:

    猜你喜欢
    • 2010-10-17
    • 2015-02-19
    • 1970-01-01
    • 2016-12-29
    • 2011-03-20
    • 1970-01-01
    相关资源
    最近更新 更多