Inicializando Ruby Hash como:

keys = [0, 1, 2]
hash = Hash[keys.each_with_object([]).to_a]

Se comporta de manera extraña al intentar insertar un valor en una clave.

hash[0].push('a')
# will result into following hash:
=> {0=>["a"], 1=>["a"], 2=>["a"]}

Solo estoy tratando de insertar en una clave, pero está actualizando el valor de todas las claves.

1
jaiswal 15 jun. 2017 a las 14:46

3 respuestas

La mejor respuesta

Sí, eso each_with_object es súper extraño en sí mismo. No es así como debería usarse. Y el problema surge precisamente porque lo usas mal.

keys.each_with_object([]).to_a
# => [[0, []], [1, []], [2, []]]

Verá, a pesar de que parece que estas matrices están separadas, en realidad es la misma matriz en los tres casos. Es por eso que si empujas un elemento en uno, aparece en todos los demás.

Aquí hay una mejor manera:

h = keys.each_with_object({}) {|key, h| h[key] = []}
# => {0=>[], 1=>[], 2=>[]}

O decir

h = keys.zip(Array.new(keys.size) { [] }).to_h

O una serie de otras formas.

Si no le importa que el hash tenga este conjunto exacto de claves y simplemente desea que todas claves tengan una matriz vacía como valor predeterminado, también es posible.

 h = Hash.new { |hash, key| hash[key] = [] }
3
Sergio Tulentsev 15 jun. 2017 a las 12:18

Todas sus claves hacen referencia a la misma matriz.

Una versión simplificada que explica el problema:

a = []
b = a
a.push('something')
puts a #=> ['something']
puts b #=> ['something']

Aunque tenga dos variables (a y b) solo hay un Array Object . Por lo tanto, cualquier cambio en la matriz referenciada por la variable a también cambiará la matriz referenciada por la variable b. Porque es el mismo objeto.

La versión larga de lo que está tratando de lograr sería:

keys = [1, 2, 3]
hash = {}
keys.each do |key|
  hash[key] = []
end

Y una versión más corta:

[1, 2 ,3].each_with_object({}) do |key, accu|
  accu[key] = []
end
0
Pascal 15 jun. 2017 a las 11:57

¿Por qué los pones en una matriz y luego los pones en un hash? Si entendí correctamente su pregunta, es posible que desee hacer esto:

hash = {'1'=>"",'2'=>"",'3'=>""}
hash['1'] = 'a'
hash['2'] = 'b'
hash['3'] = 'Hello' 

¡Puede convertirlos después de eso en un número entero o lo que desee, si la clase del objeto no satisface sus requisitos! ¡Espero eso ayude!

-1
Sergio Tulentsev 15 jun. 2017 a las 12:27