首先,这是问题和编写的代码:
def family_lineage(familytree, lineage):
'''(dict, list of strs) -> boolean
Return True if lineage specifies a list of names who are directly related
in a chain of parent-child relationships, and NOT child-parent, parent-grandchild..etc,
beginning from the first generation listed.
>>> trace_lineage({'Gina': {'Sam': {'Tina': {}},
'Li': {}},
'Guy': {}},
['Gina'])
True
>>> trace_lineage({'Gina': {'Sam': {'Tina': {}},
'Li': {}},
'Guy': {}},
['Gina', 'Sam', 'Tina'])
True
>>> trace_lineage({'Gina': {'Sam': {'Tina': {}},
'Li': {}},
'Guy': {}},
['Gina', 'Tina'])
False
'''
所以,在上面的例子中,它显示'Guy'没有孩子,而'Gina'有两个孩子,'Sam'和'Li'。 'Sam'有一个孩子,'Tina'。
for k, v in familytree.items():
for n, m in v.items():
if lineage[0] == any(k) and len(lineage) == 1:
return True
elif lineage[0] == k and lineage[1] == n and len(lineage) ==2:
return True
elif lineage[0] == k and lineage[1] == n and lineage[2] == m and \
len(lineage) == 3:
return True
else:
return False
所以,我的问题是,如果家庭树超过三代,我将如何写这个?是否有更简洁的方式编写此代码?
答案 0 :(得分:4)
这是一种迭代方法,即使lineage
没有从家谱的顶部开始也会有效:
def family_lineage(familytree, lineage):
trees = [familytree]
while trees:
tree = trees.pop()
trees.extend(t for t in tree.values() if t)
for name in lineage:
if name not in tree:
break
tree = tree[name]
else:
return True
return False
答案 1 :(得分:2)
基本上,你想看看你是否可以穿越树;使用reduce()
循环遍历元素,如果引发KeyError
,则路径不存在:
def family_lineage(familytree, lineage):
if not familytree:
return False
try:
reduce(lambda d, k: d[k], lineage, familytree)
return True
except KeyError:
# No match at this level, recurse down the family tree
return any(family_lineage(val, lineage) for val in familytree.itervalues())
reduce()
以lambda
开头递归lineage
函数。
为了支持在树的下方找到谱系,您需要在familytree
s上向下递归树。
演示:
KeyError