11
arr = ["red","green","yellow"]

arr2 = arr.clone
arr2[0].replace("blue")

puts arr.inspect
puts arr2.inspect

产生:

["blue", "green", "yellow"]
["blue", "green", "yellow"]

无论如何,除了使用 Marshal 之外,是否可以对字符串数组进行深层复制,因为我知道这是一种 hack。

我可以做:

arr2 = []
arr.each do |e|
  arr2 << e.clone
end

但它似乎不是很优雅或高效。

谢谢

4

6 回答 6

12

您的第二个解决方案可以缩短为arr2 = arr.map do |e| e.dup end(除非您确实需要 的行为clone,否则建议dup改用)。

除此之外,您的两个解决方案基本上是执行深拷贝的标准解决方案(尽管第二个版本只有一级深(即,如果您在字符串数组的数组上使用它,您仍然可以改变字符串))。真的没有更好的方法了。

编辑:这是一个适用于任意嵌套数组的递归 deep_dup 方法:

class Array
  def deep_dup
    map {|x| x.deep_dup}
  end
end

class Object
  def deep_dup
    dup
  end
end

class Numeric
  # We need this because number.dup throws an exception
  # We also need the same definition for Symbol, TrueClass and FalseClass
  def deep_dup
    self
  end
end

您可能还想为其他容器(如 Hash)定义 deep_dup,否则您仍然会得到这些容器的浅表副本。

于 2010-04-05T17:39:37.050 回答
7

我也有类似的情况,非常关心速度。对我来说最快的方法是利用map{&:clone}

所以试试这个:

pry(main)> a = (10000..1000000).to_a.shuffle.map(&:to_s)
pry(main)> Benchmark.ms { b = a.deep_dup }                                                                                     
=> 660.7760030310601
pry(main)> Benchmark.ms { b = a.join("--!--").split("--!--") }
=> 605.0828141160309
pry(main)> Benchmark.ms { b = a.map(&:clone) }
=> 450.8283680770546
于 2015-10-14T16:06:28.397 回答
5

我推荐你最初的想法,但写得更简洁一些:

arr = ["red","green","yellow"]
arr2 = arr.inject([]) { |a,element| a << element.dup }
于 2010-04-06T15:03:17.323 回答
3

a您可以通过以下代码制作数组的深层副本:

 Marshal.load(Marshal.dump(a))
于 2016-08-24T09:20:58.180 回答
2

它看起来很简单..只需运行以下代码:

a = [1,2,3]
b = [].replace(a)

b[1] = 5

puts a
puts b

运行上面的代码,你会注意到不同之处。干杯!

于 2017-01-06T06:38:48.600 回答
1

你可以使用这个技巧:

arr1 = %w{ red green blue }
arr2 = arr1.join("--!--").split("--!--")

但这只是为了好玩:)

arr2[0].replace("lol")
p arr1
#=> ["red", "green", "blue"]
p arr2
#=> ["lol", "green", "blue"]

它仅适用于 1 级数组

于 2010-04-05T18:18:25.230 回答