2011-10-17 12 views
4

ルビーを使用してマテリアライズドパスからツリー構造を構築するのに問題があります。マテリアライズドパスからツリーを構築する

[ 
    { :key => [], :value => "Home" }, 
    { :key => ["about"], :value => "About" }, 
    { :key => ["services"], :value => "Services" }, 
    { :key => ["services", "plans"], :value => "Plans" }, 
    { :key => ["services", "training"], :value => "Training" }, 
    { :key => ["services", "training", "python"], :value => "Python" }, 
    { :key => ["services", "training", "ruby"], :value => "Ruby" } 
] 

ルビー、以下のハッシュのツリーが十分であると私はこれを必要とする:

{ :title => "Home", :path => [], :children => [ 
    { :title => "About", :path => ["about"] }, 
    { :title => "Services", :path => ["services"], :children => [ 
    { :title => "Plans", :path => ["services", "plans"] } 
    ]} 
]} 

誰が助けてもらえます私は(CouchDBのから)ソートされた結果セットを持っていると仮定すると

私?

答えて

4

シンプルなヘルパークラスと再帰のビットすべてが必要です:

class Tree 
    attr_reader :root 

    def initialize 
     @root = { :title => 'Home', :path => [ ], :children => [ ] } 
    end 

    def add(p) 
     r_add(@root, p[:key].dup, p[:value]) 
     self 
    end 

    private 

    def r_add(h, path, value) 
     if(path.empty?) 
      h[:title] = value 
      return 
     end 

     p = path.shift 
     c = h[:children].find { |c| c[:path].last == p } 
     if(!c) 
      c = { :title => nil, :path => h[:path].dup.push(p), :children => [ ] } 
      h[:children].push(c) 
     end 
     r_add(c, path, value) 
    end 
end 

そして:

t = a.inject(Tree.new) { |t, h| t.add(h) } 
h = t.root 

hでこれを与える:

{:title =>"Home", :path=>[], :children=>[ 
    {:title=>"About", :path=>["about"], :children=>[]}, 
    {:title=>"Services", :path=>["services"], :children=>[ 
     {:title=>"Plans", :path=>["services", "plans"], :children=>[]}, 
     {:title=>"Training", :path=>["services", "training"], :children=>[ 
      {:title=>"Python", :path=>["services", "training", "python"], :children=>[]}, 
      {:title=>"Ruby", :path=>["services", "training", "ruby"], :children=>[]} 
     ]} 
    ]} 
]} 

することができます問題がある場合は空の:childrenを整理してください。

関連する問題