arrays - multidimensional - declarar array vacio php
¿Por qué agregar un valor a una matriz en hash también modificará la otra variable que lo tiene asignado? (5)
Código de muestra:
hash_of_array = { a: [] }
b = hash_of_array
c = hash_of_array
b[:a] << 1
puts b # => { a: [1] }
puts c # => { a: [1] }
¿Por qué ambas variables tienen 1 en su matriz? Solo lo anexé en la variable b
.
Probado
- Ruby versión 2.3.1, 2.4.0
- Rbenv
Como se mencionó anteriormente, excelentes respuestas, el problema al que se enfrenta es que a y b son el mismo objeto. Otra respuesta (más tarde eliminada) recomendaba usar el método dup, si una copia superficial era suficiente. El problema es que en tus escenarios, una copia superficial NO es lo suficientemente buena.
Propongo probar la gema full_dup. Esta gema agrega un nuevo método, llamado full_dup. Un full_dup hace una copia profunda de tus objetos. Entonces, dado tu ejemplo:
require ''full_dup''
hash_of_array = { a: [] }
b = hash_of_array.full_dup
c = hash_of_array.full_dup
b[:a] << 1
puts b # => { a: [1] }
puts c # => { a: [] }
Como un lado, full_dup no es un demonio de velocidad. Deberías usar dup regular cuando ese método es todo lo que necesitas.
Oops; Olvide mencionar. Soy el autor de la gema full_dup.
Conozco a una persona llamada John. Algunos lo llaman Johny. Johny recibió un disparo hoy. ¿Por qué John también recibió un disparo?
foo = _something_
Simplemente da el nombre alternativo foo
a _something_
. No lo clona ni hace ningún otro chanchullo.
Porque el valor de b
y el valor de c
es el mismo objeto (ver Object # object_id
):
b.object_id == c.object_id
#=> true
Todos los objetos en ruby se asignan por referencia, con la excepción de True, False, Nil y Fixnums que se manejan especialmente.
Puedes probarlo mirando object_id
irb(main):001:0> a = [1,2,3]
=> [1, 2, 3]
irb(main):002:0> b = a
=> [1, 2, 3]
irb(main):003:0> a.object_id == b.object_id
=> true
Para crear una copia de un objeto, use .dup
.
irb(main):005:0> b = a.dup
=> [1, 2, 3]
irb(main):006:0> a.object_id == b.object_id
=> false
Para su ejemplo, necesita una copia profunda, para que pueda hacer
Marshal.load(Marshal.dump(hash))
Asi que,
irb(main):037:0> a = {a: []}
=> {:a=>[]}
irb(main):038:0> b = Marshal.load(Marshal.dump(a))
=> {:a=>[]}
irb(main):039:0> b[:a] << 1
=> [1]
irb(main):040:0> b
=> {:a=>[1]}
irb(main):041:0> a
=> {:a=>[]}
En su ejemplo, y como lo menciona @AndreyDeineko , c
básicamente son el mismo objeto.
Sin embargo, no es necesario mostrar el comportamiento del que estás confundido.
Lo importante es que contienen una referencia a la misma matriz:
array = []
b = { b: array }
c = { c: array }
puts b == c
#=> false
puts b.object_id == c.object_id
#=> false
puts b[:b].object_id == c[:c].object_id
#=> true
b[:b] << ''test''
p b
# {:b=>["test"]}
p c
# {:c=>["test"]}