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

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

puts arr.inspect
puts arr2.inspect

产生

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

反正是有,因为我明白这是一个劈做一个字符串数组,比使用Marshal其他的深层副本。

我可以这样做:

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

但是它似乎没有很优雅,或高效。

由于

有帮助吗?

解决方案

您第二个解决方案可缩短至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

您可能还需要定义deep_dup其他容器(如哈希),否则你仍然会得到一个浅拷贝那些。

其他提示

我建议你最初的想法,但是写的稍微更简洁:

arr = ["red","green","yellow"]
arr2 = arr.inject([]) { |a,element| a << element.dup }

我在一个类似的情况,十分关心速度。对我来说,最快的方式是利用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

可以通过下面的代码使阵列a的深层副本:

 Marshal.load(Marshal.dump(a))

它看起来如此简单..只要运行下面的代码:

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

b[1] = 5

puts a
puts b

运行上面的代码,你会发现的差别。干杯!

您可以使用此技巧:

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

但它只是为了好玩:)

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

和它只会工作1个阵列

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top