ruby hash clone hash-of-hashes dup

Ruby dup/clone recursivamente



hash hash-of-hashes (5)

Así es como haces copias profundas en Ruby

d = Marshal.load( Marshal.dump(h) )

Tengo un hash como:

h = {''name'' => ''sayuj'', ''age'' => 22, ''project'' => {''project_name'' => ''abc'', ''duration'' => ''prq''}}

Necesito un duplicado de este hash, el cambio no debería afectar el hash original.

Cuando intento,

d = h.dup # or d = h.clone d[''name''] = ''sayuj1'' d[''project''][''duration''] = ''xyz'' p d #=> {"name"=>"sayuj1", "project"=>{"duration"=>"xyz", "project_name"=>"abc"}, "age"=>22} p h #=> {"name"=>"sayuj", "project"=>{"duration"=>"xyz", "project_name"=>"abc"}, "age"=>22}

Aquí puede ver que el project[''duration''] se cambia en el hash original porque el project es otro objeto hash.

Quiero que el hash sea duped o cloned recursivamente. ¿Cómo puedo conseguir esto?


En caso de que el par Marchal #dump/load no funcione, para los rails hay un método Hash #deep_dup , por lo que puede:

h = {''name'' => ''sayuj'', ''age'' => 22, ''project'' => {''project_name'' => ''abc'', ''duration'' => ''prq''}} h1 = h.deep_dup


Esta es una respuesta a una pregunta bastante antigua, pero me encontré con ella mientras implementaba algo similar, pensé que sería un método más eficiente.

Para el hash simple de dos niveles como el anterior, también puedes hacer algo como esto:

d = h.inject({}) {|copy, (key, value)| copy[key] = value.dup rescue value; copy }

Ejecuté una prueba en un hash de hashes con 4k elementos, cada uno de unos cientos de bytes, y fue aproximadamente un 50% más rápido que el Marshal.dump / load

Por supuesto, no es tan completo, ya que no funcionará si tiene un hash como, por ejemplo, el valor del campo ''project_name'', pero para un simple hash de 2 niveles, funciona de maravilla / más rápido.


Otra alternativa es usar la gema full_dup (descripción completa: soy el autor de esa gema) que maneja matrices, hashes, estructuras, y es extensible a las clases definidas por el usuario.

Usar:

require ''full_dup'' # Other code omitted ... d = h.full_dup

También tenga en cuenta que full_dup maneja relaciones de datos complejos, incluidos aquellos con bucles o recursión.