Ruby:如何复制这个数组?

(我之前的问题的后续行动, Ruby:如何在不指向同一对象的情况下复制变量? )

我正在编写一个简单的Ruby程序,在.svg文件中进行一些替换。 第一步是从文件中提取信息并将其放入数组中。 每次调用此函数时,为了防止从磁盘读取文件,我正在尝试使用memoize设计模式 – 在第一个调用后的每次调用时使用缓存结果。

为此,我使用了一个在函数之前定义的全局变量。 但即使我在返回局部变量之前将该变量转换为本地变量,调用此变量的函数仍在修改全局变量。

这是我的实际代码:

 #memoize to keep from having to read original file on each pass $svg_filedata_cache = [] #the global variable def svg_filedata(filename) if $svg_filedata_cache.empty? File.open(filename, "r"){|f| $svg_filedata_cache = f.readlines} end svg_filedata_cache = $svg_filedata_cache.dup #try to copy it return svg_filedata_cache #SHOULD point to a different object (but doesn't) end 

两个问题(回答其中一个或两个):

  1. 为什么接受和修改此处返回的值的其他函数也会影响全局变量,即使我使用.dup复制它?
  2. 我是Ruby的新手,我确信这不是最常用的Rubyesque方式(而且我不喜欢全局变量)。 你能提出更好的策略吗?

修改duped数组不会影响原始数据。 但是,对数组内部字符串的修改将全局可见,因为全局数组和duped数组仍包含对相同字符串的引用(dup不执行深层复制)。

因此要么执行深层复制( svg_filedata_cache = $svg_filedata_cache.map {|line| line.dup} ),要么只是避免对字符串进行变异操作。

稍微增强代码:

 $svg_filedata_cache = [] #the global variable def svg_filedata(filename) # Use ||= for memoiziation $svg_filedata_cache ||= File.open(filename, "r"){|f| $svg_filedata_cache = f.readlines} $svg_filedata_cache.dup #shallow copying end 

更新:一般来说,进行深度复制的一个简单方法是:

 def deep_copy(obj) Marshal.load(Marshal.dump(obj)) end 

全局可能没有被修改,但它和你的.dup引用的元素正在改变。 为了使它成为更规范的ruby,摆脱全局,使用类,并在initialize函数中读取文件。 (构造函数。)使用@v使数组成为实例变量。