将邻接列表转换为表

时间:2016-12-02 04:36:16

标签: python python-2.5

我在一个项目中碰到了一堵砖墙。我在数据库中有一个邻接列表,我有一系列嵌套类别。 它的格式为Id,Category,Parent_Id并且效果很好。

我希望将其显示为一个表格,以便人们可以添加和更改类别而不会产生太多混淆。这就是我失败的地方。我不能为我的生活找到如何正确显示它。

当我查询数据库时,我最终得到了一系列与此类似的嵌套元组:

((1L, 'First', None), (2L, 'Second', None), (3L, 'Third', None), (4L, 'Fourth', 1L), (5L, 'Fifth', 4L), (6L, 'Sixth', 3L), (7L, 'Seventh', 8L), (8L, 'Eighth', None))

数据有点变化,因此无法保证订单。我假设我需要某种递归函数将它变成一个表格,但我无法理解它。这样的事情会很好:

First | Fourth | Fifth 
Second
Third | Sixth
Eighth | Seventh

任何人都可以给我一些关于如何实现这一目标的指示吗?将外部模块放到我工作的盒子上几乎是不可能的,它只运行python 2.5,所以任何帮助都会非常感激。

编辑:在发布之前,我想出以下代码:

list = ((1L, 'First', None), (3L, 'Third', None), (4L, 'Fourth', 1L),
        (6L, 'Sixth', 3L), (7L, 'Seventh', 8L), (8L, 'Eighth', None), 
        (2L, 'Second', None), (5L, 'Fifth', 4L))

levels = []
levels.append([_[0] for _ in list if _[2] is None])
for x in xrange(0,len(list[0])):
   levels.append([])
   for item in list:
       levels[-1].append(item[0]) if item[2] in levels[-2] else None
   if sum([len(_) for _ in levels]) == len(list): break

从那里我得到每个级别的嵌套列表:

  

>>>水平

     

[[1L,3L,8L,2L],[4L,6L,7L],[5L]]

从这里我有点失落。我假设把它变成一个表,我需要尽可能多的列表,因为在完成的表中会有行。我可以在列表的嵌套中找到最长的列表来给出行数,它在两个维度上工作以填补表格,让我感到难过。

实际输出是非物质的。我可以用一种非常适合我的方式打印桌子。创造一张伤害我的桌子的想法。我知道可以使用Suggest SQL Query to retrieve all leaf nodes from Adjacency List Model中的SQL查询,我只是希望有一种方法可以在Python中完成,所以我可以学习更多关于处理这种数据集的知识。

1 个答案:

答案 0 :(得分:1)

不太确定预期输出的格式,但这是一种方法:

data = ((1L, 'First', None), (3L, 'Third', None), (4L, 'Fourth', 1L),
        (6L, 'Sixth', 3L), (7L, 'Seventh', 8L), (8L, 'Eighth', None), (2L, 'Second', None), (5L, 'Fifth', 4L))


def get_tuple_by_id(tuple_id):
    for item in data:
        if item[0] == tuple_id:
            return item


def arrange_data(items):
    new_list = ()

    for an_item in items:
        parent_id = an_item[2]
        if parent_id:
            parent = get_tuple_by_id(parent_id)
            new_tuple = an_item + (parent[1],)
            new_list += (new_tuple,)
        else:
            new_list += (an_item,)

    return sorted(new_list, key=lambda x: x[0])


def render(items):
    print '{name:15}{parent}'.format(name='name', parent='parent')
    print '{name:15}{parent}'.format(name='--------', parent='-------')
    for item in items:
        print '{name:15}{parent}'.format(name=item[1], parent=item[3] if item[2] else '')

ad = arrange_data(data)
render(ad)

输出:

name           parent
--------       -------
First          
Second         
Third          
Fourth         First
Fifth          Fourth
Sixth          Third
Seventh        Eighth
Eighth         

下面是一个显示表和嵌套级别的解决方案。它使用了由python 2.5支持的prettytable。

安装表格渲染器:pip install prettytable

from prettytable import PrettyTable


data = ((1L, 'First', None), (3L, 'Third', None), (4L, 'Fourth', 1L),
        (6L, 'Sixth', 3L), (7L, 'Seventh', 8L), (8L, 'Eighth', None), (2L, 'Second', None), (5L, 'Fifth', 4L))


def get_tuple_by_id(tuple_id):
    for item in data:
        if item[0] == tuple_id:
            return item


def arrange_data(items):
    new_list = ()

    for an_item in items:
        parent_id = an_item[2]
        if parent_id:
            parent = get_tuple_by_id(parent_id)
            new_tuple = an_item + (parent[1],)
            new_list += (new_tuple,)
        else:
            new_list += (an_item,)

    return sorted(new_list, key=lambda x: x[0])


ad = arrange_data(data)
t = PrettyTable(['Category', 'Level'])

for item in ad:
    t.add_row([item[1], 1 if item[2] else 0])

print t

结果:

+----------+-------+
| Category | Level |
+----------+-------+
|  First   |   0   |
|  Second  |   0   |
|  Third   |   0   |
|  Fourth  |   1   |
|  Fifth   |   1   |
|  Sixth   |   1   |
| Seventh  |   1   |
|  Eighth  |   0   |
+----------+-------+

注意:如果数据是嵌套的多级,那么一些修改也可以实现。目前它只考虑0或1级嵌套。

以下使用递归函数处理多级嵌套:

from prettytable import PrettyTable


data = (
    (1L, 'First', None), 
    (2L, 'Second', None), 
    (3L, 'Third', None), 
    (4L, 'Fourth', 1L),
    (5L, 'Fifth', 4L),
    (6L, 'Sixth', 3L), 
    (7L, 'Seventh', 8L), 
    (8L, 'Eighth', None), 
    (9L, 'Ninth', 5L),
    (10L, 'Tenth', 9L),
    (11L, 'Eleventh', 10L),
    (12L, 'Twelfth', 11L))


def get_tuple_by_id(tuple_id, level=1):
    for item in data:
        if item[0] == tuple_id:
            parent_id = item[2]
            if parent_id:
                level += 1
                return get_tuple_by_id(parent_id, level)
            else:
                return (item, level)


def arrange_data(items):
    new_list = ()

    for an_item in items:
        parent_id = an_item[2]
        if parent_id:
            parent, level = get_tuple_by_id(parent_id)
            print an_item, level

            new_tuple = an_item + (level,)
            new_list += (new_tuple,)
        else:
            an_item += (0,)
            new_list += (an_item,)

    return sorted(new_list, key=lambda x: x[0])


ad = arrange_data(data)
t = PrettyTable(['Category', 'Level'])

for item in ad:
    t.add_row([item[1], item[3]])

print t

输出:

+----------+-------+
| Category | Level |
+----------+-------+
|  First   |   0   |
|  Second  |   0   |
|  Third   |   0   |
|  Fourth  |   1   |
|  Fifth   |   2   |
|  Sixth   |   1   |
| Seventh  |   1   |
|  Eighth  |   0   |
|  Ninth   |   3   |
|  Tenth   |   4   |
| Eleventh |   5   |
| Twelfth  |   6   |
+----------+-------+

如果您感兴趣,请提供有关递归函数的更多信息:https://en.wikipedia.org/wiki/Recursion_(computer_science)