【发布时间】:2015-11-28 10:48:07
【问题描述】:
我正在尝试在 Python 中实现一些基本的递归结构,但没有取得很大成功。我有一棵以嵌套列表形式表示的树,如下所示:
ex = ['A',
['A1',
['A11', 'tag'],
['A12', 'tag'],
['A13',
['A131', 'tag'],
['A132',
['A1321', 'tag'],
['A1322', 'tag']]]],
['A2', 'tag'],
['A3',
['A31',
['A311', 'tag'],
['A312', 'tag']],
['A32', 'tag'],
['A33',
['A331',
['A3311', 'tag'],
['A3312', 'tag']]],
['A34', 'tag'],
['A35',
['A351', 'tag'],
['A352',
['A3521', 'tag'],
['A3522', 'tag']]]],
['A4', 'tag']]
我已经定义了一个 Node 类,它允许指定标签 'A', 'A1', ... 并添加子级。通过注意到children 不是一个列表,可以检索终端节点。
class Node(object):
def __init__(self, tag, parent=None, children=[]):
self.tag = tag
self.parent = parent
self.children = children
self.is_terminal = False if isinstance(children, list) else True
def add_child(self, node):
if not isinstance(node, Node):
raise ValueError("Cannot append node of type: [%s]" % type(node))
if self.is_terminal:
raise ValueError("Cannot append node to terminal")
else:
self.children.append(node)
现在我无法实现一个函数,该函数会将基于列表的树递归地转换为基于节点的树:
tree = Node(tag='A',
children=[Node(tag='A1',
children=[Node(tag='A11',
children='tag'),
Node(tag='A12',
children='tag'),
...]),
...])
这是我迄今为止的尝试,基于这样一种想法,即在嵌套列表中的每个位置,我们可能有一个终端节点,在这种情况下,我们只需将其添加到根节点,或者是一个非终端节点,在这种情况下我们提取相应的根标签并递归地遍历子标签。当列表为空时,我们将控制权返回给调用者。 我的感觉是编码风格可能不是最适合 Python,但我想更具体地知道我缺少什么。
def is_terminal(e):
return len(e) == 2 and type(e[0]) == str and type(e[1]) == str
def from_list(lst, root):
lst = list(lst) # avoid mutating input list
if not lst:
return
for e in lst:
if is_terminal(e):
tag, children = e
print "terminal", tag, "with root", root.tag
root.add_child(Node(tag=tag, children=children, parent=root))
else:
e = list(e)
tag, children = e.pop(0), e
print "non terminal", tag, "with root", root.tag
root = Node(tag=tag, parent=root)
from_list(children, root=root)
它有很多问题。例如,它丢失了最高根'A' -i.e. A2 获取 A1 作为根。它还将树展平为具有 16 个子节点的节点,每个终端节点一个,并进入无限递归。
我会很感激任何类型的提示。
【问题讨论】: