2009-08-19 7 views
3

Je charge un document YAML arbitraire et je souhaite parcourir chaque nœud de l'arborescence. Je ne sais pas à quel point l'arbre est imbriqué à l'avance, donc je ne peux pas simplement utiliser une simple instruction pour marcher tous les nœuds.Comment parcourir tous les nœuds d'une arborescence YAML dans Ruby?

Voici comment je charger le document:

tree = File.open("#{RAILS_ROOT}/config/locales/es.yml"){ |yf| YAML::load (yf)} 
+2

Tout d'abord, laissez-moi vous parler de YAML :: load_file (chemin) – kch

+0

-vous au moins savoir ce que le nœud racine est? Hacher? Array? Y a-t-il du tout un format pour les nœuds suivants ou tout est-il inconnu? Puis-je supposer que vous voulez traverser les hachages et les tableaux, et que toute autre chose est une feuille? – kch

+0

Pouvez-vous poster un exemple de fichier yaml pour gist ou pastie ou quelque part et le lier ici? Aussi, pouvez-vous nous donner une idée de ce que vous voulez faire pendant la traversée? Agir sur les feuilles? – kch

Répondre

12
def traverse(obj, &blk) 
    case obj 
    when Hash 
    # Forget keys because I don't know what to do with them 
    obj.each {|k,v| traverse(v, &blk) } 
    when Array 
    obj.each {|v| traverse(v, &blk) } 
    else 
    blk.call(obj) 
    end 
end 

traverse(YAML.load_file(filename)) do |node| 
    puts node 
end 

Edit:

Notez que ce ne donne que les nœuds feuilles. La question n'était pas très claire quant à ce que l'on voulait exactement.

+0

sepp2k: les nœuds feuille est exactement ce que je voulais, c'est parfait! –

+0

ajouté la capacité d'agir sur les branches, et de passer le nœud parent à bloquer, basé sur @ sepp2k grand anaswer. – 1gor

4

Voici comment analyser une structure arborescente YAML et agir sur chaque nœud, branche et feuille. Il vous donne également le parent de chaque nœud dont vous avez besoin, par exemple, lors du remplissage d'une arborescence de base de données à partir de votre fichier YAML. Il est un petit plus de @ sepp2k excellente réponse:

require 'yaml' 

def traverse(obj,parent, &blk) 
case obj 
when Hash 
    obj.each do |k,v| 
    blk.call(k,parent) 
    # Pass hash key as parent 
    traverse(v,k, &blk) 
    end 
when Array 
    obj.each {|v| traverse(v, parent, &blk) } 
else 
    blk.call(obj,parent) 
end 
end 


# Example, creating a database tree structure, from your YAML file. 
# Passing nil to root node(s) as parent 

tree_str =<<EOF 
    Regions: 
    - Asia 
    - Europe 
    - Americas 
    Other: 
    - Foo: 
     - bar 
     - buz 
EOF 

traverse(YAML.load(tree_str), nil) do |node,parent| 
    puts "Creating node '#{node}' with parent '#{ parent || 'nil' }'" 
end