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

时间:2021-12-29 21:37:58

I have a 2-dimensional array in Ruby that I want to produce a working duplicate of. Obviously I can't do this;

我在Ruby中有一个二维数组,我想要生成一个工作副本。显然我不能这么做;

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

as any modifications I make to temp_array will also be made to array, as I have merely copied the object identifier. I thought I would be able to get around this by simply using;

正如我对temp_array所做的任何修改一样,也将对array进行修改,因为我只是复制了对象标识符。我想我可以通过简单地使用;

temp_array=array.dup

but this doesn't work as temp_array is simply an array of object identifiers that get duplicated so I still end up modifying the initial array (if I understand what went wrong when I did this). The solution I found was to do the following;

但这并不奏效,因为temp_array只是一个重复的对象标识符数组,所以我最终还是修改了初始数组(如果我理解出错的原因的话)。我找到的解决方案是:

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

This achieves what I want but seems to be an awkward way of solving my problem.

这达到了我想要的,但似乎是解决我的问题的一种笨拙的方式。

I am concerned about how this would work if I didn't know what my array was going to be containing (e.g. if it was possible that some parts of the array had 3-dimensions). I would potentially have to test the class of each member of the array to see if it had to be iterated over in order to duplicate it. Not an impossible task at all, but it seems messy to me. Is this simply a consequence of Ruby lacking built-in support for multidimensional arrays or is there a simple built-in function to do this that I have missed?

我关心的是,如果我不知道我的数组将包含什么(例如,如果数组的某些部分可能是三维的),这将如何工作。我可能需要测试数组中每个成员的类,看看是否需要迭代它才能复制它。这并不是一项不可能完成的任务,但在我看来,它似乎很混乱。这仅仅是Ruby缺乏对多维数组的内置支持的结果吗?还是有一个简单的内置函数可以实现这一点?

7 个解决方案

#1


30  

Here's the "Ruby-esque" way to handle it:

这里有一个“ruby式”的处理方法:

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

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

#2


3  

There is the best way of making exact and real copy of the multidimensional array in Ruby is Marshalling.

在Ruby中,最好的方法是编组,这样才能准确、真实地复制多维数组。

Here is the Ruby syntax of marshalling:

下面是封送的Ruby语法:

Marshal.load(Marshal.dump(Name_Of_Your_Original_Array))

Marshal.load(Marshal.dump(Name_Of_Your_Original_Array))

Let's see how to use this syntax using the above example i.e.

让我们看看如何使用上面的例子即。

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

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

In this example it only create an object which points the same memory location of the array, it's not doing the real copy of our array. Here, If you modify the value of your temp_array then it'll automatically reflect the changes in the original array which is array variable in our example. So how do we prevent the automatic changes happen in our original array, we can do this by marshalling.

在本例中,它只创建一个指向数组相同内存位置的对象,而不执行数组的实际拷贝。在这里,如果您修改temp_array的值,那么它将自动反映原始数组中的更改,在我们的示例中,该数组是数组变量。如何防止原始数组中的自动更改发生,我们可以通过编组来实现。

So! how do we do this, in the example we need to make a real copy of the array into the temp_array.

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

Let's see, how to do this :

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

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

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

Now, we've done the real copy of our multidimensional array, if you modify any value of your temp_array then the changes will not reflect your original array.

现在,我们已经完成了多维数组的真正副本,如果您修改了temp_array的任何值,那么这些更改将不会反映您的原始数组。

#3


2  

As other people have pointed out, you can use clone. This will not work, however, as it's a shallow copy, so the sub arrays (this is not really a multidimensional array, I think) will not get cloned. Since arrays are mutable objects in Ruby, the sub arrays will get changed. For instance, check this out

正如其他人指出的,你可以使用克隆技术。但是,这将不起作用,因为它是一个浅拷贝,所以子数组(我认为这不是一个真正的多维数组)不会被克隆。由于数组是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]

So as you can see, just doing clone will not work. But you knew that, hence your question.

正如你所看到的,仅仅做克隆是行不通的。但你知道,因此你的问题。

I cooked this up just now. This will do until you find out the real, Ruby way to do it (I just work in Ruby, I'm not an expert).

我刚才把它做熟了。这将在您发现真正的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

I know, I'm not using duck-typing, but I'd be glad to be schooled as to how to do this without asking for the class of the object in question.

我知道,我不是在使用duck-typing,但我很高兴能在不询问所讨论对象的类别的情况下被教会如何做到这一点。

Edit: I should've just searched on deep-clone ruby in Google, but sometimes I like writing code :)... anyway, the other solution presented -- Marshal.load( Marshal.dump( array ) ) -- will also work for Hashes and so forth, so it's way better.

编辑:我应该在谷歌中搜索深度克隆ruby,但有时我喜欢写代码:)……不管怎样,提出的另一个解决方案,Marshal。负载(元帅。转储(数组))——也将用于哈希等,所以它更好。

#4


0  

You can use DeepEnumerable's deep_dup for this:

您可以使用深化可拓的deep_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]]

#5


-1  

Try running array.dup on each sub-array within the array.

尝试运行数组。数组中每个子数组的dup。

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

#6


-7  

Try this:

试试这个:

temp_array = array.clone

#7


-8  

You can use array.clone as specified here. That will give you a copy of the original object, and not just a pointer.

您可以使用数组。克隆在这里指定。这会给你一个原始对象的拷贝,而不仅仅是一个指针。

#1


30  

Here's the "Ruby-esque" way to handle it:

这里有一个“ruby式”的处理方法:

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

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

#2


3  

There is the best way of making exact and real copy of the multidimensional array in Ruby is Marshalling.

在Ruby中,最好的方法是编组,这样才能准确、真实地复制多维数组。

Here is the Ruby syntax of marshalling:

下面是封送的Ruby语法:

Marshal.load(Marshal.dump(Name_Of_Your_Original_Array))

Marshal.load(Marshal.dump(Name_Of_Your_Original_Array))

Let's see how to use this syntax using the above example i.e.

让我们看看如何使用上面的例子即。

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

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

In this example it only create an object which points the same memory location of the array, it's not doing the real copy of our array. Here, If you modify the value of your temp_array then it'll automatically reflect the changes in the original array which is array variable in our example. So how do we prevent the automatic changes happen in our original array, we can do this by marshalling.

在本例中,它只创建一个指向数组相同内存位置的对象,而不执行数组的实际拷贝。在这里,如果您修改temp_array的值,那么它将自动反映原始数组中的更改,在我们的示例中,该数组是数组变量。如何防止原始数组中的自动更改发生,我们可以通过编组来实现。

So! how do we do this, in the example we need to make a real copy of the array into the temp_array.

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

Let's see, how to do this :

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

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

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

Now, we've done the real copy of our multidimensional array, if you modify any value of your temp_array then the changes will not reflect your original array.

现在,我们已经完成了多维数组的真正副本,如果您修改了temp_array的任何值,那么这些更改将不会反映您的原始数组。

#3


2  

As other people have pointed out, you can use clone. This will not work, however, as it's a shallow copy, so the sub arrays (this is not really a multidimensional array, I think) will not get cloned. Since arrays are mutable objects in Ruby, the sub arrays will get changed. For instance, check this out

正如其他人指出的,你可以使用克隆技术。但是,这将不起作用,因为它是一个浅拷贝,所以子数组(我认为这不是一个真正的多维数组)不会被克隆。由于数组是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]

So as you can see, just doing clone will not work. But you knew that, hence your question.

正如你所看到的,仅仅做克隆是行不通的。但你知道,因此你的问题。

I cooked this up just now. This will do until you find out the real, Ruby way to do it (I just work in Ruby, I'm not an expert).

我刚才把它做熟了。这将在您发现真正的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

I know, I'm not using duck-typing, but I'd be glad to be schooled as to how to do this without asking for the class of the object in question.

我知道,我不是在使用duck-typing,但我很高兴能在不询问所讨论对象的类别的情况下被教会如何做到这一点。

Edit: I should've just searched on deep-clone ruby in Google, but sometimes I like writing code :)... anyway, the other solution presented -- Marshal.load( Marshal.dump( array ) ) -- will also work for Hashes and so forth, so it's way better.

编辑:我应该在谷歌中搜索深度克隆ruby,但有时我喜欢写代码:)……不管怎样,提出的另一个解决方案,Marshal。负载(元帅。转储(数组))——也将用于哈希等,所以它更好。

#4


0  

You can use DeepEnumerable's deep_dup for this:

您可以使用深化可拓的deep_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]]

#5


-1  

Try running array.dup on each sub-array within the array.

尝试运行数组。数组中每个子数组的dup。

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

#6


-7  

Try this:

试试这个:

temp_array = array.clone

#7


-8  

You can use array.clone as specified here. That will give you a copy of the original object, and not just a pointer.

您可以使用数组。克隆在这里指定。这会给你一个原始对象的拷贝,而不仅仅是一个指针。