2009-08-19 102 views
3

我正在加載任意的YAML文檔,並且想要遍歷樹中的每個節點。我不知道如何預先嵌套樹,所以我不能只使用簡單的每條語句遍歷所有節點。如何遍歷Ruby中YAML樹中的所有節點?

這裏是我如何加載文檔:

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

首先,讓我告訴你關於YAML :: LOAD_FILE(路徑) – kch 2009-08-19 21:10:58

+0

你至少知道根節點是什麼?哈希?陣列?後續節點中是否有任何格式或全部未知?我可以假設你想要遍歷哈希和數組,而其他的東西都是葉子? – kch 2009-08-19 21:12:17

+0

你可以發佈一個示例yaml文件來要麼或pastie或某個地方,並在這裏鏈接?另外,你能告訴我們在遍歷過程中你想做什麼嗎?在樹葉上行事? – kch 2009-08-19 21:14:58

回答

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 

編輯:

注意,這僅產生葉子節點。這個問題並不十分清楚究竟是什麼意思。

+0

sepp2k:葉節點是正確的我想要什麼,這是完美的! – 2009-08-20 01:08:15

+0

基於@ sepp2k偉大的anaswer增加了對分支行爲的處理能力,並通過父節點進行阻止。 – 1gor 2013-06-29 06:23:27

4

這裏是如何解析YAML樹結構並對每個節點,分支和葉節點採取行動。它還爲您提供您需要的每個節點的父項,例如,在從YAML文件填充數據庫樹結構時。這是一個小除了@ sepp2k出色答卷:

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