Comment affecter le hachage ['a'] ['b'] = 'c' si le hachage ['a'] n'existe pas?
-
28-10-2019 - |
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
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.