【问题标题】:How do I process a nested list?如何处理嵌套列表?
【发布时间】:2010-06-06 03:19:36
【问题描述】:

假设我有一个像这样的项目符号列表:

* list item 1
* list item 2 (a parent)
** list item 3 (a child of list item 2)
** list item 4 (a child of list item 2 as well)
*** list item 5 (a child of list item 4 and a grand-child of list item 2)
* list item 6

我想将其解析为嵌套列表或其他一些数据结构,这使得元素之间的父子关系显式(而不是取决于它们的内容和相对位置)。例如,这是一个包含一个项目及其子项列表(等等)的元组列表:

编辑:希望是一个更正确的列表示例,其中列表中的每个元素都是一个元组,其中包含:项目符号的文本以及(如果适用)子列表(以相同的形式)。

罢工>

[('列表项 1',), ('list item 2', [('list item 3',), ('list item 4', [('list item 5',)])] ('列表项 6',)]

[('list item 1',),
 ('list item 2', [('list item 3',), ('list item 4', [('list item 5',)])]),
 ('list item 6',)]

我尝试使用纯 Python 和 Pyparsing 进行一些实验,但我没有取得进展。我有两个主要问题:

  1. 我需要采用什么策略来完成这项工作?我知道递归是解决方案的一部分,但我很难在这个和斐波那契数列之间建立联系。
  2. 我确定我不是第一个这样做的人,但我不知道该问题的术语,以便对有关此主题的更多信息进行富有成效的搜索。与此相关的问题是什么,以便我可以了解更多关于解决这类问题的一般信息?

【问题讨论】:

  • 我想如果你能在这里发布你的尝试,人们可能会更好地帮助你!
  • 您是否正在尝试解析组织模式文件?也许你可以从 orgnode 中获得灵感,看看他是如何完成解析的。 members.optusnet.com.au/~charles57/GTD/orgnode.html
  • @Lazer:很抱歉,但我并没有真正有用的尝试样本。令我沮丧的是,我没有检查版本控制,我的尝试剩下的东西没有运行。 =\ @pygabriel:我不是在尝试解析 org-mode,但感谢您提供的链接。我肯定会很快花一些时间来回顾一下。这可能是鼓舞人心的。如果它很有价值,我想做的是制作和使用超级简单的清单格式。

标签: python parsing list


【解决方案1】:

从搜索算法的角度来看,你给出的子弹其实是一个深度优先搜索生成的序列。所以我的策略就是用dfs-sequence重建树形结构。

以下是python代码:

from collections import deque
def dfsBullet(bullet,depth):
    """
       parse the subtree with depth and the startnode of bullet[0]
    """
    li = []
    if depth != 0:
            item = bullet.popleft()
            li.append(item.split(' ',1)[1])
    while (len(bullet) != 0):
            item = bullet[0]
            #apply same algo to the child node
            if len(item.split(' ',1)[0]) > depth:
                    sublist = dfsBullet(bullet, len(item.split(' ')[0]))
            #we have traverse all childnode, so go back 
            else:
                    return li
            #add child tree to the list
            li.append(sublist)
    return li

【讨论】:

    【解决方案2】:

    我无法解析您想要的结果——它的开括号似乎比相应的闭括号要多,我不明白它背后的逻辑。

    要使树结构显式,例如:

    data = '''* list item 1
    * list item 2
    ** list item 3
    ** list item 4
    *** list item 5
    * list item 6'''.splitlines()
    
    class Node(object):
      def __init__(self, payload):
        self.payload = payload
        self.children = []
      def show(self, indent):
        print ' '*indent, self.payload
        for c in self.children:
          c.show(indent+2)
    
    def makenest(linelist):
      rootnode = Node(None)
      stack = [(rootnode, 0)]
      for line in linelist:
        for i, c in enumerate(line):
          if c != '*': break
        stars, payload = line[:i], line[i:].strip()
        curlev = len(stars)
        curnod = Node(payload)
        while True:
          parent, level = stack[-1]
          if curlev > level: break
          del stack[-1]
        # a child node of the current top-of-stack
        parent.children.append(curnod)
        stack.append((curnod, curlev))
      rootnode.show(0)
    
    makenest(data)
    

    show 方法的存在当然只是为了验证关于解析字符串和创建树的部分是否正常工作。如果您可以更准确地指定要将树转换为嵌套元组和列表的方式,我相信向Node 类添加适当的(可能是递归的)方法会很容易——所以,能否请您给出这个缺失的规范...?

    编辑:由于 OP 现在已经澄清,它确实如预期的那样容易满足规范。只需将以下方法添加到class Node:

      def emit(self):
        if self.children:
          return (self.payload,
                  [c.emit() for c in self.children])
        else:
          return (self.payload,)
    

    并将代码的最后三行(makenest 的最后一行、空白行和对makenest 的模块级调用)更改为:

      return [c.emit() for c in rootnode.children]
    
    print(makenest(data))
    

    (print 后面的括号在 Python 2 中是多余但无害的,在 Python 3 中是必需的,所以我把它们放在那里以防万一;-)。

    通过这些微小的更改,我的代码按要求运行,现在发出

    [('list item 1',), ('list item 2', [('list item 3',), ('list item 4', [('list item 5',)])]), ('list item 6',)]
    

    【讨论】:

    • 感谢您的回答,亚历克斯。根据要求,我用一个更正确的例子来编辑我的问题,说明我正在努力完成什么。让我知道这是否可以解决问题。
    • 感谢您的回复。这是我最终采用的方法,效果很好。谢谢!
    【解决方案3】:

    跟踪您正在解析的当前“深度”。

    • 如果下一行的深度大于当前深度,则递归调用具有新深度的解析器,然后将该调用的结果添加到当前列表中。
    • 如果下一行的深度等于当前深度,则将其添加到当前列表中。
    • 如果下一行的深度小于当前深度,则返回当前列表。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-17
      • 2011-06-18
      • 1970-01-01
      相关资源
      最近更新 更多