复制 Ruby 字符串数组

Posted

技术标签:

【中文标题】复制 Ruby 字符串数组【英文标题】:Duplicating a Ruby array of strings 【发布时间】:2011-02-04 12:16:31 【问题描述】:
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

但它看起来不是很优雅,也不是很高效。

谢谢

【问题讨论】:

你可以做更短的内联块:arr.each|e| arr2 【参考方案1】:

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

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

b[1] = 5

puts a
puts b

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

【讨论】:

【参考方案2】:

您可以通过以下代码对数组a 进行深拷贝:

 Marshal.load(Marshal.dump(a))

【讨论】:

【参考方案3】:

我也有类似的情况,非常关心速度。对我来说最快的方法是使用map&amp;: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

【讨论】:

【参考方案4】:

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

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

【讨论】:

如果您的数组具有像整数这样的 FixNums,则 DUP 会出现问题 - 无法复制 Fixnum ***.com/questions/1964143/… ***.com/questions/19165957/ruby-cant-dup-fixnum【参考方案5】:

您的第二个解决方案可以缩短为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,否则您仍然会得到这些容器的浅拷贝。

【讨论】:

感谢您的回答sepp2k,所以如果您有嵌套数组,唯一的方法就是使用Marshal? @Jon:不,您也可以定义递归 deep_dup 方法(请参阅我的编辑),但使用 Marshal 通常更容易。 你不能通过在 Object 中定义 deep_dup 来避免修补 Numeric 等吗?:respond_to?(:dup) ? dup : 自我 @Lars:不,因为数字确实会响应 dup。他们只是通过抛出异常来响应。 @sepp2k:真没意思。然后像 [Numeric, Symbol, TrueClass, FalseClass].include?(self.class) ?自我:重复;应该做的伎俩。【参考方案6】:

你可以使用这个技巧:

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

但这只是为了好玩:)

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

它只适用于 1 级数组

【讨论】:

只有当数组只包含字符串并且没有字符串包含“--!--”作为子字符串时,它才会起作用。 sepp2k,是的,它只是为了一个目的而破解 :) 就像 tetra pack

以上是关于复制 Ruby 字符串数组的主要内容,如果未能解决你的问题,请参考以下文章

rails/ruby字符串与数组之间的转换

rails/ruby字符串与数组之间的转换

如何在Ruby中将数组数组转换为一个字符串[关闭]

Ruby - 遍历数组中的每个字符串并删除重复的字符

Ruby 1.9:将字节数组转换为具有多字节 UTF-8 字符的字符串

Ruby - 比较数组和交换索引