2010-12-10 50 views
31

Je suis en train d'initialiser une table de hachage de tableaux tels queComment puis-je initialiser un tableau dans une table de hachage en Ruby

@my_hash = Hash.new(Array.new) 

afin que je puisse:

@my_hash["hello"].push("in the street") 
=> ["in the street"] 
@my_hash["hello"].push("at home") 
=> ["in the street", "at home"] 
@my_hash["hello"] 
=>["in the street", "at home"] 

Le problème est que toute nouvelle clé de hachage également retourner ["in the street", "at home"]

@my_hash["bye"] 
=> ["in the street", "at home"] 
@my_hash["xxx"] 
=> ["in the street", "at home"] 

!!! ??? Qu'est-ce que je fais de mal quelle serait la bonne façon d'initialiser un Hash of Arrays?

+0

connexes: http://stackoverflow.com/questions/190740/setting-ruby-hash-default-to-a-list – tokland

Répondre

83
@my_hash = Hash.new(Array.new) 

Cela crée exactement un objet tableau, qui est retourné à chaque fois qu'une clé est introuvable. Puisque vous ne faites que muter ce tableau et n'en créez jamais un nouveau, toutes vos clés sont mappées au même tableau.

Qu'est-ce que vous voulez faire est:

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

ou simplement

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

Le passage d'un bloc à Hash.new diffère de passer simplement un argument de 2 façons:

  1. Le Le bloc est exécuté chaque fois qu'une clé n'est pas trouvée. Ainsi, vous obtiendrez un nouveau tableau à chaque fois. Dans la version avec un argument, cet argument est évalué une fois (avant que new soit appelé) et le résultat de cela est retourné à chaque fois.

  2. En faisant h[k] = vous insérez réellement la clé dans le hachage. Si vous ne le faites pas, l'accès à @my_hash[some_key] ne provoquera pas l'insertion de some_key dans le hachage.

+14

Celui Gotcha à être au courant ici est que maintenant même * vérification * a La clé va le créer, ce qui peut ne pas être ce que vous voulez. Pour cette raison, je crée parfois le Hash normalement (avec juste {}), et ensuite je fais la création de tableau dans l'appel, comme '(@myhash [" bonjour "] || = []). Push (" dans la rue ")". –

2

L'argument pour Hash.new est la valeur par défaut pour les nouvelles clés de hachage, donc lorsque vous le passez une référence sera utilisée pour les nouvelles clés de hachage. Vous mettez à jour cette référence lorsque vous appelez ...

hash["key"].push "value" 

Vous devez passer une nouvelle référence dans la clé de hachage avant de pousser les valeurs à elle ...

hash["key1"] = Array.new 
hash["key1"].push "value1" 
hash["key2"] = Array.new 
hash["key2"].push "value2 

Vous pouvez essayer cette encapsulation dans une méthode d'aide ainsi.

7

Essayez ceci:

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