Cómo asignar hash = ‘c’ si hash no existe?

¿Hay alguna manera más simple que

if hash.key?('a') hash['a']['b'] = 'c' else hash['a'] = {} hash['a']['b'] = 'c' end 

La forma más fácil es construir su Hash con un argumento de bloque:

 hash = Hash.new { |h, k| h[k] = { } } hash['a']['b'] = 1 hash['a']['c'] = 1 hash['b']['c'] = 1 puts hash.inspect # "{"a"=>{"b"=>1, "c"=>1}, "b"=>{"c"=>1}}" 

Este formulario para new crea un nuevo Hash vacío como valor predeterminado. Usted no quiere esto:

 hash = Hash.new({ }) 

ya que usará exactamente el mismo hash para todas las entradas predeterminadas.

Además, como señala Phrogz, puedes hacer que los hash auto-vivificados se auto-vivifiquen usando default_proc :

 hash = Hash.new { |h, k| h[k] = Hash.new(&h.default_proc) } 

ACTUALIZACIÓN : Creo que debería aclarar mi advertencia contra Hash.new({ }) . Cuando dices esto:

 h = Hash.new({ }) 

Eso es más o menos como decir esto:

 h = Hash.new h.default = { } 

Y luego, cuando accedes h para asignar algo como h[:k][:m] = y , se comporta como si lo hubieras hecho:

 if(h.has_key?(:k)) h[:k][:m] = y else h.default[:m] = y end 

Y luego, si h[:k2][:n] = z , terminará asignando h.default[:n] = z . Tenga en cuenta que h todavía dice que h.has_key?(:k) es falso.

Sin embargo, cuando dices esto:

 h = Hash.new(0) 

Todo saldrá bien porque nunca modificará h[k] en su lugar aquí, solo leerá un valor de h (que usará el valor predeterminado si es necesario) o le asignará un nuevo valor a h .

uno simple, pero el hash debería ser un objeto hash válido

 (hash["a"] ||= {})['b'] = "c" 

Si crea hash como el siguiente, con el valor predeterminado de un nuevo hash (valor predeterminado idéntico): (gracias a Phrogz por la corrección, tuve la syntax incorrecta)

 hash = Hash.new{ |h,k| h[k] = Hash.new(&h.default_proc) } 

Entonces puedes hacer

 hash["a"]["b"] = "c" 

sin ningún código adicional.

La pregunta aquí: ¿Es posible la inicialización automática de la matriz de hash multidimensional en Ruby, como lo es en PHP? proporciona una implementación AutoHash muy útil que hace esto.

 class NilClass def [](other) nil end end 

Una vez que haya definido eso, todo funcionará automáticamente. Pero tenga en cuenta que de ahora en adelante, nil se comportaría como un hash vacío cuando se usa como hash.

Intereting Posts