11
arr = ["red","green","yellow"]

arr2 = arr.clone
arr2[0].replace("blue")

puts arr.inspect
puts arr2.inspect

生成:

["blue", "green", "yellow"]
["blue", "green", "yellow"]

とにかく、マーシャルを使用する以外に、文字列の配列のディープコピーを行う方法はありますか?それはハックだと理解しています。

私はそれをできた:

arr2 = []
arr.each do |e|
  arr2 << e.clone
end

しかし、それは非常にエレガントでも効率的でもないようです。

ありがとう

4

6 に答える 6

12

2 番目のソリューションは次のように短縮できますarr2 = arr.map do |e| e.dup end(実際に の動作が必要でない限り、代わりcloneに使用することをお勧めしますdup)。

それ以外の 2 つのソリューションは、基本的にディープ コピーを実行するための標準的なソリューションです (ただし、2 番目のバージョンは 1 レベルの深さしかありません (つまり、文字列の配列の配列で使用する場合でも、文字列を変更できます))。これ以上良い方法はありません。

編集:これは、任意にネストされた配列で機能する再帰的な 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 を定義することもできます。そうしないと、それらの浅いコピーが取得されます。

于 2010-04-05T17:39:37.050 に答える
7

私も同様の状況にあり、速度が非常に心配です。私にとって最速の方法は、map{&: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
于 2015-10-14T16:06:28.397 に答える
5

最初のアイデアをお勧めしますが、もう少し簡潔に書きます。

arr = ["red","green","yellow"]
arr2 = arr.inject([]) { |a,element| a << element.dup }
于 2010-04-06T15:03:17.323 に答える
3

a次のコードで、配列のディープ コピーを作成できます。

 Marshal.load(Marshal.dump(a))
于 2016-08-24T09:20:58.180 に答える
2

とてもシンプルに見えます..以下のコードを実行するだけです:

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

b[1] = 5

puts a
puts b

上記のコードを実行すると、違いがわかります。乾杯 !

于 2017-01-06T06:38:48.600 に答える
1

このハックを使用できます:

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

しかし、それはただの楽しみです:)

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

そして、それは1レベルの配列に対してのみ機能します

于 2010-04-05T18:18:25.230 に答える