ruby hash variable-assignment autovivification hash-of-hashes

ruby - ¿Cómo asignar el hash[''a''][''b'']=''c'' si el hash[''a''] no existe?



variable-assignment autovivification (5)

¿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 valor de hash vacío como valor predeterminado. Usted no quiere esto:

hash = Hash.new({ })

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

Además, como señala Phrogz, puede hacer que los hash vivificados automáticamente se vivifiquen utilizando 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 muy parecido a decir esto:

h = Hash.new h.default = { }

Y luego, cuando accede a h para asignar algo como h[:k][:m] = y , se comporta como si hiciera esto:

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

Y luego, si h[:k2][:n] = z , terminarás 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] aquí, solo leerá un valor de h (que usará el valor predeterminado si es necesario) o asignará un nuevo valor a h .



Si crea un hash como el siguiente, con el valor predeterminado de un nuevo hash (idénticamente con un valor predeterminado): (gracias a Phrogz por la corrección; tuve la sintaxis 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.


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

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


class NilClass def [](other) nil end end

Una vez que hayas 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 usara como un hash.