Question

Y a-t-il un moyen plus simple que

if hash.key?('a')
  hash['a']['b'] = 'c' 
else  
  hash['a'] = {}
  hash['a']['b'] = 'c' 
end
Était-ce utile?

La solution

Le moyen le plus simple est de Construisez votre hachage avec un argument de bloc:

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}}"

Cette forme pour new Crée un nouveau hachage vide comme valeur par défaut. Vous ne voulez pas ceci:

hash = Hash.new({ })

comme cela utilisera le exactement la même hachage pour toutes les entrées par défaut.

De plus, comme le note Phrogz, vous pouvez rendre les hachages auto-vivifiés auto-vivifier en utilisant default_proc:

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

METTRE À JOUR: Je pense que je devrais clarifier mon avertissement contre Hash.new({ }). Quand tu dis ceci:

h = Hash.new({ })

C'est un peu comme dire ceci:

h = Hash.new
h.default = { }

Et puis, lorsque vous accédez h Affecter quelque chose comme h[:k][:m] = y, il se comporte comme si vous l'aviez fait:

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

Et puis, si vous h[:k2][:n] = z, vous finirez par attribuer h.default[:n] = z. Notez que h dit toujours que h.has_key?(:k) c'est faux.

Cependant, quand vous dites ceci:

h = Hash.new(0)

Tout va bien fonctionner parce que vous n'aurez jamais modifié h[k] En place ici, vous ne lirez qu'une valeur de h (qui utilisera la valeur par défaut si nécessaire) ou affectera une nouvelle valeur à h.

Autres conseils

Un simple, mais le hachage devrait être un objet de hachage valide

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

Si vous créez hash Comme ce qui suit, avec une valeur par défaut d'un nouveau hachage (identique à valeur par défaut): (grâce à Phrogz pour la correction; j'avais mal la syntaxe)

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

Alors tu peux faire

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

sans code supplémentaire.

La question ici:L'auto-initialisation du réseau de hachage multidimensionnel est-elle possible dans Ruby, comme dans PHP?fournit un très utile AutoHash implémentation qui le fait.

class NilClass
  def [](other)
    nil
  end
end

Une fois que vous avez défini cela, tout fonctionnera automatiquement. Mais sachez que maintenant nil se comporterait comme un hachage vide lorsqu'il est utilisé comme hachage.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top