【问题标题】:Sorting data hierarchically对数据进行分层排序
【发布时间】:2013-01-07 02:34:42
【问题描述】:

我的 python 程序返回一个包含子列表数据的列表。每个子列表都包含一篇文章的唯一 ID 和该文章的父 ID,即

pages_id_list ={ {22, 4},{45,1},{1,1}, {4,4},{566,45},{7,7},{783,566}, {66,1},{300,8},{8,4},{101,7},{80,22}, {17,17},{911,66} }

在每个 sub-list 中,数据的结构都是这样{*article_id*, *parent_id*} 如果 article_id 和 parent_id 相同,则显然该文章没有父级。

我想使用最少的代码对数据进行排序,这样对于每篇文章,我都可以轻松地 如果可用,访问它的子孙(嵌套数据)列表。例如(使用上面的示例数据)我应该能够在一天结束时打印:

 1
 -45
 --566
 ---783
 -66
 --911

....对于文章 ID 1

我只能整理出最高级别(第一代和第二代)的 ID。获得第 3 代及后续代时遇到问题。

这是我使用的代码:

highest_level = set()
first_level = set()
sub_level = set()

for i in pages_id_list:
    id,pid = i['id'],i['pid']

    if id == pid:
        #Pages of the highest hierarchy
        highest_level.add(id)

for i in pages_id_list:
    id,pid = i['id'],i['pid']

    if id != pid :
        if pid in highest_level:
            #First child pages
            first_level.add(id)
        else:
            sub_level.add(id)

很遗憾,我的代码不起作用。

我们将不胜感激任何朝着正确方向的帮助/推动。 谢谢

大卫

【问题讨论】:

  • 您是否尝试过使用while 循环?

标签: python list sorting set hierarchical-data


【解决方案1】:

可能是这样的:

#! /usr/bin/python3.2

pages_id_list = [ (22, 4),(45,1),(1,1), (4,4),(566,45),(7,7),(783,566), (66,1),(300,8),(8,4),(101,7),(80,22), (17,17),(911,66) ]

class Node:
    def __init__ (self, article):
        self.article = article
        self.children = []
        self.parent = None

    def print (self, level = 0):
        print ('{}{}'.format ('\t' * level, self.article) )
        for child in self.children: child.print (level + 1)

class Tree:
    def __init__ (self): self.nodes = {}

    def push (self, item):
        article, parent = item
        if parent not in self.nodes: self.nodes [parent] = Node (parent)
        if article not in self.nodes: self.nodes [article] = Node (article)
        if parent == article: return
        self.nodes [article].parent = self.nodes [parent]
        self.nodes [parent].children.append (self.nodes [article] )

    @property
    def roots (self): return (x for x in self.nodes.values () if not x.parent)

t = Tree ()
for i in pages_id_list: t.push (i)
for node in t.roots: node.print ()

这将创建一个树结构,您可以遍历该结构以获取所有子项。您可以通过t.nodes [article] 访问任何文章并通过t.nodes [article].children 获取其子项。

print方法的输出是:

1
    45
        566
            783
    66
        911
4
    22
        80
    8
        300
7
    101
17

【讨论】:

  • +1 用于节点/树对象 - 恕我直言,更容易理解。您甚至可以覆盖 __str__ 函数而不是使用 node.print()?
  • 另外请记住,如果递归深度超过 1000 层,Python 会抛出错误。 (本部分:child.print (level + 1)
  • 如果预计树将有超过 1000 个级别,您应该取消递归打印函数。
【解决方案2】:

这是一个简单的方法(假设您的页面 id 列表元素没有设置,如您的代码所示):

from collections import defaultdict

page_ids = [
    (22, 4), (45, 1), (1, 1), (4, 4),
    (566, 45), (7, 7), (783, 566), (66, 1), (300, 8),
    (8, 4), (101, 7), (80, 22), (17, 17), (911, 66)
]

def display(id, nodes, level):
    print('%s%s%s' % ('  ' * level, '\\__', id))
    for child in sorted(nodes.get(id, [])):
        display(child, nodes, level + 1)

if __name__ == '__main__':
    nodes, roots = defaultdict(set), set()

    for article, parent in page_ids:
        if article == parent:
            roots.add(article)
        else:
            nodes[parent].add(article)

    # nodes now looks something like this:
    # {1: [45, 66], 66: [911], 4: [22, 8], 22: [80], 
    #  7: [101], 8: [300], 45: [566], 566: [783]}

    for id in sorted(roots):
        display(id, nodes, 0)

输出将是:

\__1
  \__45
    \__566
      \__783
  \__66
    \__911
\__4
  \__8
    \__300
  \__22
    \__80
\__7
  \__101
\__17

来源:https://gist.github.com/4472070

【讨论】:

  • @Hyperboreus,我在回答中解释了。
  • Miku 虽然我更喜欢不需要模块的解决方案,但了解这一点很有用。在此之前从未对集合模块做过太多工作。谢谢
【解决方案3】:

我想使用最少的代码对数据进行排序

直到现在我才读到这篇文章,因此我将提供另一个答案。我不会编辑我之前的答案,因为它们真的不相关。如果您想用最少的代码将元组列表转换为树结构,那么这种方法非常简单,尽管它仍然可以进一步最小化(例如,使用递归 lambda 项而不是函数):

pages_id_list = [ (22, 4),(45,1),(1,1), (4,4),(566,45),(7,7),(783,566), (66,1),(300,8),(8,4),(101,7),(80,22), (17,17),(911,66) ]

def getTree (item, pages): return [ (x, getTree (x, pages) ) if getTree (x, pages) else x for x in (x [0] for x in pages if x [1] == item) ]

tree = getTree (None, [ (x [0], None if x [0] == x [1] else x [1] ) for x in pages_id_list] )

【讨论】:

  • 感谢 Hyperboreus。由于代码最少,这对我最有用。
  • 请记住,虽然计算成本非常高。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-14
  • 1970-01-01
  • 2023-03-19
  • 1970-01-01
  • 1970-01-01
  • 2020-09-13
相关资源
最近更新 更多