Ruby:如何复制这个数组?

Nat*_*ong 5 ruby

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

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

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

这是我的实际代码:

#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
Run Code Online (Sandbox Code Playgroud)

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

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

sep*_*p2k 9

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

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


khe*_*lll 6

稍微增强代码:

$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
Run Code Online (Sandbox Code Playgroud)

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

def deep_copy(obj)
  Marshal.load(Marshal.dump(obj))
end
Run Code Online (Sandbox Code Playgroud)

  • 它表示只有在尚未设置该变量的情况下才将右侧值分配给左侧变量. (2认同)