Ruby 从关系树到对象树的转换

5swords · 2014年04月16日 · 1756 次阅读

工作中用到把表里的树显示到页面上,写了一个小程序来验证,不知大家会不会用到。

records       = [{
  :name       => '01',
  :id         => 1
},{
  :name       => '0101',
  :id         => 2
},{
  :name       => '010101',
  :id         => 3
},{
  :name       => '010102',
  :id         => 4
},{
  :name       => '010103',
  :id         => 5
},{
  :name       => '02',
  :id         => 6
},{
  :name       => '0201',
  :id         => 7
},{
  :name       => '0202',
  :id         => 8
},{
  :name       => '020201',
  :id         => 9
},{
  :name       => '020202',
  :id         => 10
},{
  :name       => '0203',
  :id         => 11
},{
  :name       => '03',
  :id         => 12
},{
  :name       => '04',
  :id         => 13
},{
  :name       => '0401',
  :id         => 14
},{
  :name       => '040101',
  :id         => 15
},{
  :name       => '04010101',
  :id         => 16
}]

class TreeNode
  attr_accessor :name, :id, :children
  def initialize(r)
    @name = r[:name]
    @id = r[:id]
  end

  def length
    @name.length
  end

  def push_child(node)
    @children ||= []
    @children.push node
  end

  def to_hash
    result = {name: @name, id: @id}
    @children.nil? ? result : result.merge!(children: @children.collect(&:to_hash))
  end
end

stack = [TreeNode.new({:name => ''})]
is_debug = false

records.each do |r|
  node = TreeNode.new(r)
  puts "#{node.id}: #{node.name}\n" if is_debug
  stack.pop while stack.last.length >= node.length
  stack.last.push_child node
  stack.push node
  puts "#{stack.collect(&:to_hash)}\n" if is_debug
end
stack.first.children.collect(&:to_hash)

=> [{:name=>"01", :id=>1, :children=>[{:name=>"0101", :id=>2, :children=>[{:name=>"010101", :id=>3}, {:name=>"010102", :id=>4}, {:name=>"010103", :id=>5}]}]}, {:name=>"02", :id=>6, :children=>[{:name=>"0201", :id=>7}, {:name=>"0202", :id=>8, :children=>[{:name=>"020201", :id=>9}, {:name=>"020202", :id=>10}]}, {:name=>"0203", :id=>11}]}, {:name=>"03", :id=>12}, {:name=>"04", :id=>13, :children=>[{:name=>"0401", :id=>14, :children=>[{:name=>"040101", :id=>15, :children=>[{:name=>"04010101", :id=>16}]}]}]}]

暂无回复。
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册