<p>我建议,假设你可以相信名字之间没有重复,比如:</p>
<pre><code>class Node(object):
byname = {}
def __init__(self, name, parent=None):
self.name = name
self.parent = parent
self.children = []
self.byname[name] = self
if parent is None: # root pseudo-node
self.code = 0
else: # all normal nodes
self.parent.children.append(self)
self.code = len(self.parent.children)
def get_codes(self, codelist):
if self.code:
codelist.append(str(self.code))
self.parent.get_codes(codelist)
root = Node('')
def get_code(nodename):
node = Node.byname.get(nodename)
if node is None: return ''
codes = []
node.get_codes(codes)
codes.reverse()
return '.'.join(codes)
</code></pre>
<p>您是否还想查看Python代码,以了解如何在给定名称的层次序列(例如<code>['Africa', 'North Africa', 'Morocco']</code>)的情况下添加节点?我希望在上面的结构下它会很清楚,所以你可能想自己做一个练习,但是当然要问你是否愿意看到一个解决方案;-)。在</p>
<p>从文本行(字符串)中获取名称的层次序列取决于分隔符是什么——在您的示例中,它看起来像是纯粹为了美观而添加的一堆空格,与列的排列有关(如果是这样的话,我建议使用一个简单的基于<code>re</code>的方法来拆分两个+空格的序列),但是如果它实际上是(例如)制表符作为分隔符,那么Python标准库中的<code>csv</code>模块将更好地为您服务。我只是不能从你在Q中发布的一个简短的例子来判断!-)在</p>
<p><strong>编辑</strong>:OP说他们可以很好地获得名称序列,但希望看到从这些节点添加相关节点的代码——所以,开始吧!-)在</p>
^{pr2}$
<p>了解为什么节点名是唯一的,这对于使上面的类工作很重要吗?由于<code>Node.byname</code>是每个类的一个<code>dict</code>,它只能为每个给定的名称记录一个“对应的节点”——因此,在层次结构中的两个或多个位置重复的名称将“冲突”,并且只有两个或多个节点中的一个将被正确记录。在</p>
<p>但话说回来,这个函数<code>get_code</code>是整个设备无法正常工作的主要原因,如果一个名称可能是模棱两可的,因为操作的规范要求它只返回<em>一个</em>字符串。所以,一些地理列表</p>
<pre><code>America United States Georgia
Europe Eastern Europe Georgia
</code></pre>
<p>(当两个完全不相关的区域同时被命名为<code>'Georgia'</code>——正如上面的例子所示,这种不幸的事情经常发生在现实世界中!-)会破坏整个方案(取决于<code>get_code</code>的规范如何碰巧被修改以处理一个模棱两可的名称参数,当然,类结构肯定会相应地改变,以适应新的、完全不同的规范!)。在</p>
<p>将这些设计决策封装在一个类中的好处是(尽管在这个例子中有几个附带的函数——它们可以优雅地被制作成类方法,当然,但是OP的规范严格要求<code>get_code</code>是一个函数,所以我决定,在这种情况下,<code>addnodes</code>也可以是一个函数!-)具体的设计决策大部分是隐藏在代码的其余部分中的,因此可以很容易地修改(当然,只要规范永远不变——这就是为什么花时间和精力定义自己的API规范如此重要,这比设计和编码的任何其他部分都重要得多!-)重构内部行为(例如为了优化、易于调试/测试等等),同时保持API指定的语义不变,从而使应用程序的所有其他部分保持原始状态(实际上,甚至不需要重新测试,当然,只要实现API的部分都经过了非常彻底的单元测试——不难做到,因为它们很好地隔离和独立!-). 在</p>