最近,我不得不遍历一棵树,从任意节点开始直到它的根。我写了一些类似的东西
breadcrumbs = []
while node is not None:
breadcrumbs.append(node.get_text())
node = node.get_parent()
在我看来,它看起来很像使用列表构造的丑陋实现
result = []
while node is not None:
result.append(node.get_text())
node = node.next()
而不是更惯用的列表理解
result = [node.get_text() for node in nodes]
这让我想知道是否有一种更惯用的从树遍历构造列表的方法。为了完整起见(并且由于上面的摘录主要是伪代码),这是我使用的实际代码:
model, treeiter = self.treeview.get_selection().get_selected()
breadcrumbs = []
while treeiter is not None:
breadcrumbs.append(model.get_value(treeiter, self.COL_TEXT))
treeiter = model.iter_parent(treeiter)
path = '/'.join(reversed(breadcrumbs))
对于上下文,第一行调用Gtk.TreeSelection.get_selected(其返回值之一在API中称为iter
,但与Python迭代器无关)。我的代码从用户选择的路径(例如,在下面的示例中为"A/b/2"
)创建一个字符串:
+- A
| |- a
| \- b
| |- 1
| \- 2 <- selected element
\- B
|- c
\- d
答案 0 :(得分:3)
是的,您使用的树结构不是非常pythonic。但是,您可以使用自制的generators轻松地将其转换为更具Python风格的解决方案。
例如,要遍历父母(或祖先),您可以定义一个iter_parents
函数,如下所示:
def iter_parents(node):
while node is not None:
yield node
node = node.get_parent()
有了这个,您可以像这样构建面包屑:
breadcrumbs = [node.get_text() for node in iter_parents(branch)]
这是一个小演示:
class Node(object):
def __init__(self, text, parent=None):
self._text = text
self._parent = parent
def get_text(self):
return self._text
def get_parent(self):
return self._parent
branch = Node("c", Node("b", Node("a")))
breadcrumbs = [node.get_text() for node in iter_parents(branch)]
print(breadcrumbs)
# -> ['c', 'b', 'a']
对于node.next()
,您可以以相同的方式定义iter_next()
生成器。
修改
使用reverse
来反转列表,例如:
breadcrumbs = [node.get_text() for node in iter_parents(branch)]
breadcrumbs.reverse()
print(breadcrumbs)
# -> ['a', 'b', 'c']
答案 1 :(得分:0)
当然,您可以将while循环包装在这样的生成器中:
def get_parents(node):
while node is not None:
yield node
node.get_parent()
然后您可以使用:
result = [node.get_text() for node in get_parents(nodes)]