如何从平面关系表中重新组合分层数据?

时间:2014-11-13 22:34:46

标签: python relational-database

我试图弄清楚如何将表示分层数据的表转换回代码。

表格配置如下:

| id | parent_id | name | 
|----|-----------|------|
| 1  |   null    | foo  |
| 2  |    1      | bar  |
| 3  |    1      | baz  | 
| 4  |    3      | bif  | 
| 5  |    1      | zip  | 

etc...  

这样,在重建时,它看起来像这样:

foo
 |-bar
 |-baz
    |-bif
 |-zip

我正在努力寻找一种在内存中构建此列表的非可怕方法。

基本上,我所遇到的解决方案只是强行推进。例如(伪Python)

output = {}
for item in table:
   parent = get_parent(item) 
   if parent: 
       if parent not in output:  
           output[parent] = []
       output[parent_item].append(item) 

然而,这只会让我走到一半。它正确地将孩子们置于他们的直接父母之下,但只有一个级别。这个数据大约有3个级别,所以我想我必须继续迭代它,直到我找不到父母的任何对象。

我只想说,我的解决方案很糟糕,很脆弱,而且我不知道还能做什么。解决这个问题的正确方法是什么?

1 个答案:

答案 0 :(得分:0)

检查此快速解决方案。

我们可以构建一个字典,因此我们可以使用名称映射键。

D={"1":"foo","2":"bar","3":"baz","4":"bif","5":"zip","Non":'Root'}
get_parent_id=["Non","1","1","3","1"]
get_name=["foo","bar","baz","bif","zip"]

result = {} 
for k,v in zip(get_parent_id,get_name):
    result.setdefault(D[k], {}).update({v:{}})

我们从parent ids和名字建立一个字典。

{'baz': {'bif': {}}, 'foo': {'baz': {}, 'bar': {}, 'zip': {}}, 'Root': {'foo': {}}}

现在,我们必须处理其他值。我们可以使用布尔字典{key:boolean value}来标记哪个是根,每当我们找到一个键作为键时,我们将其标记为false,因为它不能成为根。

正式地,Root是一个不会出现在所有键值中的键。

boolRoot= len(result)*[True]
bDict=dict(zip(result.keys(),boolRoot))

# {'Root': True, 'foo': True, 'baz': True}   

然后,我们遍历值,我们用键和映射到子项的值替换里面的值

for k,v in result.iteritems():
    for item in v.keys():
        #print item,result[k][item]
        if item in result.keys():
            bDict[item]=False
            result[k][item]=result[item]

print result
print bDict

最后,我们会:

{'baz': {'bif': {}}, 'foo': {'baz': {'bif': {}}, 'bar': {}, 'zip': {}}, 'Root': {'foo': {'baz': {'bif': {}}, 'bar': {}, 'zip': {}}}} #result
{'Root': True, 'foo': False, 'baz': False} #bDict

Root是基于上述假设的值为True的键。您只需获取result[name],其中bDict[name] is True

希望能帮助你找到更好的解决方案。