How to handle a nested list?

Suppose I have a bulleted list:

* 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

I would like to parse this into a nested list or some other data structure that makes the relationship between parents and children explicit (and not depending on their content and relative position). For example, here is a list of tuples containing an element and a list of its child elements (etc.):

Change . We hope that a more correct example is a list where each element in the list is a tuple containing: bullet text and, if applicable, a list of children (in the same form).

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

Strike>

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

Python Pyparsing, . :

  • , ? , , , , .
  • , , , , . , ?
+3
3

- , , , .

, ,

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 (, , ) - ...?

: , , , . 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',)]
+2

, , , Depth-First-Search. , dfs.

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
+5

"", .

  • , , .
  • If the depth of the next line is equal to the current depth, add it to the current list.
  • If the depth of the next line is less than the current depth, return the current list.
+1
source

Source: https://habr.com/ru/post/1748701/


All Articles