从相关对象构建树

时间:2013-11-01 10:25:29

标签: ruby arrays algorithm multidimensional-array

我需要构建这个树:

result = [
  ['t9'],
  ['t3',   
    ['t4'],
    ['t8',   
      ['t6'],
      ['t1',
        ['t5']
      ]
    ]
  ],
  ['t7',
    ['t2']
  ]
]

来自这些对象:

{:id => 't1', :tg => 't8', :rank => 2}
{:id => 't2', :tg => 't7', :rank => 1}
{:id => 't3', :tg => nil, :rank => 2}
{:id => 't4', :tg => 't3', :rank => 1}
{:id => 't5', :tg => 't1', :rank => 1}
{:id => 't6', :tg => 't8', :rank => 1}
{:id => 't7', :tg => nil, :rank => 3}
{:id => 't8', :tg => 't3', :rank => 2}
{:id => 't9', :tg => nil, :rank => 1}

tg是自引用关联。 rank是数组中的位置/索引

任何想法(红宝石首选)?

3 个答案:

答案 0 :(得分:3)

def combine e, a
  a
  .inject([]){|a, h| a[h[:rank] - 1] = [h[:id]] if h[:tg] == e; a}
  .map{|e| e + combine(e.first, a)}
end

combine(nil, [
  {:id => 't1', :tg => 't8', :rank => 2},
  {:id => 't2', :tg => 't7', :rank => 1},
  {:id => 't3', :tg => nil, :rank => 2},
  {:id => 't4', :tg => 't3', :rank => 1},
  {:id => 't5', :tg => 't1', :rank => 1},
  {:id => 't6', :tg => 't8', :rank => 1},
  {:id => 't7', :tg => nil, :rank => 3},
  {:id => 't8', :tg => 't3', :rank => 2},
  {:id => 't9', :tg => nil, :rank => 1},
])
# => [["t9"], ["t3", ["t4"], ["t8", ["t6"], ["t1", ["t5"]]]], ["t7", ["t2"]]]

答案 1 :(得分:0)

听起来你正在建造像树一样的东西。该算法可以归纳如下:

  1. 找到所有节点:tg为零,然后得到[t3,t7,t9]
  2. 在[t3,t7,t9]中找到所有节点:tg,然后返回[t4,t8]
  3. 在[t4,t8]中找到所有节点:tg ...

答案 2 :(得分:0)

使用递归(基于@ cenyongh的树概念)

def tree(arr,parent=nil)
    arr.select{|n| n[:tg] == parent}.
            sort_by{|n| n[:rank]}.
            map{|n| [n[:id]] +  tree(arr,n[:id])}
end

# call
tree(array_of_objects)