Paramètres par défaut à plusieurs niveaux Hash lors de l'accès non-Existant clés comme dans h [1] [1] + = 1 [double]

StackOverflow https://stackoverflow.com/questions/3576008

  •  01-10-2019
  •  | 
  •  

Question

    

Cette question a déjà une réponse ici:

         

Je suis en train de créer un Hash de Hash-es. La valeur du 2ème hachage de niveau est un entier par défaut à 0. Ce que je suis en train de faire est de commencer par un hachage vide de hash, puis quand j'ajoute une valeur si la clé n'existe pas, ils la clé doit être ajoutée avec une valeur par défaut.

Lorsque je tente ce avec un simple Hash d'entiers, il fonctionne très bien:

irb(main):003:0> h = Hash.new(0)
=> {}
irb(main):004:0> h[1] += 1
=> 1
irb(main):005:0> p h
{1=>1}
=> nil
irb(main):006:0> h.keys.size
=> 1
irb(main):007:0>

h a maintenant une clé et une valeur de 1. Parfait.

Mais quand les valeurs de hachage sont mon hash, il ne semble pas au travail:

irb(main):007:0> h = Hash.new(Hash.new(0))
=> {}
irb(main):008:0> h[1][1] += 1
=> 1
irb(main):009:0> p h
{}
=> nil
irb(main):010:0> h.keys.size
=> 0
irb(main):011:0>

Ai-je fait quelque chose de mal, ou je ne peux pas définir la valeur par défaut pour un hachage Hash.new(0)?

EDIT:

Sur la base des réponses ci-dessous, je suis en mesure de comprendre ce que je faisais mal. En fait, j'ai pu savoir où ma pensée était défectueuse. Longue histoire courte, h[1][1] fait des appels Hash.new pas de nid, à moins que vous donnez Hash.new un bloc de code à l'appel. La valeur de l'expression h[1][1] += 1 est 1 comme prévu, mais seulement le hachage le plus intérieur est en cours d'initialisation correctement.

Je poste parce que tout mon exemple ci-dessus utilise un hachage 2 dimensions, mon problème réel utilise un hachage en 3 dimensions:

syms[level][exchange][symbol] = count

La solution pourrait être utile pour les autres ayant ce problème, voici donc le code qui obtient ce travail comme je le veux:

irb(main):024:0> syms = Hash.new{|h1,k1| h1[k1] = Hash.new{|h2,k2| h2[k2] = Hash.new(0)}}
=> {}
irb(main):026:0> syms["level1"]["NYSE"]["IBM"] += 1
=> 1
irb(main):027:0> p syms
{"level1"=>{"NYSE"=>{"IBM"=>1}}}
=> nil
irb(main):028:0>
Était-ce utile?

La solution

La façon la plus générale de définir une valeur par défaut lors de la création d'un Hash est d'utiliser la nouvelle fonction Hash # avec un argument de bloc:

h = Hash.new { |h, k| h[k] = Hash.new(0) }

Le problème que vous avez est que vous définissez la valeur par défaut à un pointeur d'objet plutôt que d'un morceau de code à exécuter. C'est, à chaque fois qu'une valeur manquante dans le hachage « externe » est accessible, il renvoie un pointeur sur la exactement la même objet. Pour le prouver à vous-même, essayez ceci:

>> h = Hash.new(Hash.new(0))
=> {}
>> h[1] === h[2]
=> true

Vous peut , en fait, définir la valeur par défaut pour un hachage, mais cela ne sera pas accomplir ce que vous voulez. Incrémentation h [1] [1] va dans le changement de fait le hachage par défaut lui-même, puisque h [1] n'a pas été initialisé.

Hope this helps.

Autres conseils

h = Hash.new(Hash.new(0))

Le Hash.new (0) est l'objet par défaut; il est le même objet pour chaque touche non existant. Il est juste ce que les déclarations de hachage lorsque la clé est pas là.

h = Hash.new{|h,k| h[k]=Hash.new(0)}

{| h, k | h [k] = Hash.new (0)} est l'option par défaut Proc. Il fonctionne lorsque la clé est absent et il crée une clé pour chaque non-existant nouveau hachage (par défaut à 0.).

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