有没有一种在Ruby中复制多维数组的简单方法?

时间:2010-01-11 00:20:43

标签: ruby arrays multidimensional-array

我在Ruby中有一个二维数组,我想生成一个有效的副本。显然我不能这样做;

array=[[3,4],[5,9],[10,2],[11,3]]
temp_array=array

因为我对temp_array所做的任何修改也将对数组进行修改,因为我只是复制了对象标识符。我以为我可以通过简单地使用来解决这个问题;

temp_array=array.dup

但是这不起作用,因为temp_array只是一个对象标识符的数组,它会被复制,所以我最终还是修改了初始数组(如果我理解了什么时候出错了)。我发现的解决方案是执行以下操作;

temp_array=[]
array.each{|sub| temp_array << sub.dup}

这实现了我的目标,但似乎是解决问题的一种尴尬方式。

如果我不知道我的数组将包含什么(例如,如果阵列的某些部分可能具有3维),我担心这将如何工作。我可能必须测试数组的每个成员的类,看看是否必须迭代它才能复制它。根本不是一项不可能的任务,但对我来说似乎很麻烦。这仅仅是Ruby缺乏对多维数组的内置支持的结果,还是有一个简单的内置函数来执行此操作而我错过了?

7 个答案:

答案 0 :(得分:33)

这是处理它的“ Ruby-esque ”方式:

temp_array = Marshal.load(Marshal.dump(your_array_to_be_cloned))

答案 1 :(得分:4)

正如其他人所指出的那样,你可以使用克隆。然而,这不起作用,因为它是一个浅层副本,所以子数组(我认为这不是一个多维数组)不会被克隆。由于数组是Ruby中的可变对象,因此子数组将会发生变化。例如,检查一下

>> blah = [[3,5],6]
=> [[3, 5], 6]
>> joe = blah.clone
=> [[3, 5], 6]
>> joe[0]
=> [3, 5]
>> joe[0].push "blah"
=> [3, 5, "blah"]
>> blah
=> [[3, 5, "blah"], 6]

正如您所看到的,只是做克隆将无法正常工作。但你知道,因此你的问题。

我刚刚把它煮熟了。这样做直到你发现真正的Ruby方式(我只是在Ruby工作,我不是专家)。

def dup_recursive(new_array, old_array)
  old_array.each do |item|
    if item.class == Array
      new_array << dup_recursive([], item)
    else
      new_item = item.dup rescue new_item = item # in case it's got no dupe, like FixedNum
      new_array << new_item
    end
    new_array
  end
end

array=[[3,[9,12]],[5,9],[10,2],[11,3]]
new_array = Array.new
dup_recursive(new_array, array)
puts array.inspect
puts new_array.inspect

我知道,我不是在使用鸭子打字,但我很乐意接受如何做到这一点,而不需要问相关对象的类。

编辑:我应该只搜索Google中的深度克隆ruby,但有时我喜欢编写代码:)...无论如何,提出了另一个解决方案 - Marshal.load( Marshal.dump( array ) ) - 也适用于哈希等等,所以它更好。

答案 2 :(得分:4)

在Ruby中 编组< 多维数组的最佳方法是完全真实副本 / EM>

以下是 编组 Ruby 语法:

Marshal.load(Marshal.dump(Name_Of_Your_Original_Array))

让我们看看如何使用上面的示例

来使用这种语法

array=[[3,4],[5,9],[10,2],[11,3]] temp_array=array

在这个例子中,它只创建一个指向数组相同内存位置的对象,它不是我们数组的真实副本。在这里,如果您修改了temp_array的值,那么它会自动反映原始数组中的变化,在我们的示例中为array变量。那么我们如何防止在原始数组中发生自动更改,我们可以通过编组来实现。

原来如此!我们如何做到这一点,在示例中我们需要将 数组 的真实副本复制到 temp_array

让我们看看,如何做到这一点:

array=[[3,4],[5,9],[10,2],[11,3]] temp_array = Marshal.load(Marshal.dump(array))

现在,我们已经完成了多维数组的真实副本,如果您修改temp_array的任何值,则更改将不会反映您的原始array

答案 3 :(得分:0)

您可以使用DeepEnumerabledeep_dup

>> require 'deep_enumerable'

>> array=[[3,4],[5,9],[10,2],[11,3]]

>> temp_array=array.deep_dup
>> array.each{|sub| sub << "XXX"}

>> array
=> [[3, 4, "XXX"], [5, 9, "XXX"], [10, 2, "XXX"], [11, 3, "XXX"]]

>> temp_array
=> [[3, 4], [5, 9], [10, 2], [11, 3]]

答案 4 :(得分:-1)

尝试在阵列中的每个子阵列上运行array.dup。

    c = []
    array.each do |row|
      c << row.dup
    end

答案 5 :(得分:-8)

试试这个:

temp_array = array.clone

答案 6 :(得分:-9)

您可以使用指定herearray.clone。这将为您提供原始对象的副本,而不仅仅是指针。