2008-10-04 5 views
34

La création de hachages de hachage dans Ruby permet des recherches de deux dimensions (ou plus). Cependant, lors de l'insertion, il faut toujours vérifier si le premier index existe déjà dans le hachage. Par exemple:Hachis de hambres Idiome en rubis?

h = Hash.new 
h['x'] = Hash.new if not h.key?('x') 
h['x']['y'] = value_to_insert 

Il serait préférable de faire ce qui suit où le nouveau Hash est automatiquement créé:

h = Hash.new 
h['x']['y'] = value_to_insert 

De même, lors de la recherche d'une valeur où le premier indice n'existe pas déjà, il serait préférable que nil soit retourné plutôt que de recevoir une méthode non définie pour l'erreur '[]'.

looked_up_value = h['w']['z'] 

On pourrait créer une classe wrapper Hash qui a ce comportement, mais est-il un existant un langage Ruby pour accomplir cette tâche?

+0

est-il un hachage des idiomes de hachage qui reviendraient 0 après une certaine profondeur? (Je compte des choses et j'utilise h [: foo] [: bar] [: baz] + = 1) –

Répondre

54

Vous pouvez passer la fonction Hash.new un bloc qui est exécuté pour donner une valeur par défaut dans le cas où la valeur recherchée n'existe pas encore:

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

Bien sûr, cela peut être fait de manière récursive.

/EDIT: Wow, il y a an article répondant à cette question.

Par souci d'exhaustivité, voici la solution de l'article pour hash de profondeur arbitraire:

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

Crédits vont à Kent de Data Noise.

+1

Wow. C'est impressionnant. –

+0

Lien mort. Solution impressionnante cependant. –

+1

Le lien mort est commuté ici http://inquirylabs.com/blog2009/2006/09/20/ruby-hashes-of-arbitrary-depth/ – Autodidact

4

L'autovivification, comme on l'appelle, est à la fois une bénédiction et une malédiction. Le problème peut être que si vous "regardez" une valeur avant qu'elle ne soit définie, vous êtes coincé avec ce hachage vide dans la fente et vous devrez l'élaguer plus tard.

Si cela ne vous dérange pas un peu d'anarchie, vous pouvez toujours confiture ou égal à des déclarations de style qui vous permettront de construire la structure attendue comme vous l'interroger:

((h ||= { })['w'] ||= { })['z']