Pregunta

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

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

puts arr.inspect
puts arr2.inspect

produce:

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

¿Hay alguna forma de hacer una copia profunda de una matriz de cadenas, con excepción de usar Mariscal como yo entiendo que es un truco.

lo que podía hacer:

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

pero no parece muy elegante, o eficiente.

Gracias

¿Fue útil?

Solución

Su segunda solución se puede acortar a arr2 = arr.map do |e| e.dup end (a menos que realmente necesita el comportamiento de clone, se recomienda el uso dup en su lugar).

Aparte de que sus dos soluciones son básicamente las soluciones estándar para realizar una copia profunda (aunque la segunda versión es sólo un nivel profundo (es decir, si la utiliza en una serie de matrices de cadenas, todavía puede mutar las cuerdas )). En realidad no hay una manera más agradable.

Edit: Aquí está un método recursivo deep_dup que trabaja con matrices arbitrariamente anidados:

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

También puede ser que desee para definir deep_dup para otros recipientes (como Hash), de lo contrario tendrá todavía obtener una copia superficial para aquellos.

Otros consejos

Recomiendo su idea inicial, pero escrito un poco más concisa:

arr = ["red","green","yellow"]
arr2 = arr.inject([]) { |a,element| a << element.dup }

Estoy en una situación similar y muy preocupados por la velocidad. La forma más rápida para mí era hacer uso de map{&:clone}

Así que trate esto:

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

Se puede hacer una copia en profundidad de la matriz a por código siguiente:

 Marshal.load(Marshal.dump(a))

Parece tan simple .. Sólo tiene que ejecutar el siguiente código:

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

b[1] = 5

puts a
puts b

Ejecutar el código anterior y se dará cuenta de la diferencia. Saludos!

Se puede utilizar este truco:

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

Pero es sólo por diversión:)

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

Y funcionará sólo para matrices de nivel 1

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top