我正在使用这个gist's单行树轻松地从excel中获取信息。以下是该网站树的示例:
def tree(): return defaultdict(tree)
taxonomy = tree()
taxonomy['Animalia']['Chordata']['Mammalia']['Carnivora']['Felidae']['Felis']['cat']
taxonomy['Animalia']['Chordata']['Mammalia']['Carnivora']['Felidae']['Panthera']['lion']
taxonomy['Animalia']['Chordata']['Mammalia']['Carnivora']['Canidae']['Canis']['dog']
然后将其转换为dicts以进行漂亮打印:
def dicts(t):
try:
return dict((k, dicts(t[k])) for k in t)
except TypeError:
return t
澄清
如何从树上返回密钥?具体来说,树中的前三层键将被获取并放入列表中。一个例子是:
('Animalia', 'Chordata', 'Mammalia','Plantae', 'Solanales', 'Convolvulaceae')
的
{'Animalia': {'Chordata': {'Mammalia': {'Carnivora': {'Canidae': {'Canis': {'coyote': {},
'dog': {}}},
'Felidae': {'Felis': {'cat': {}},
'Panthera': {'lion': {}}}},
'Cetacea': {'Balaenopteridae': {'Balaenoptera': {'blue whale': {}}}}}}},
'Plantae': {'Solanales': {'Convolvulaceae': {'Ipomoea': {'sweet potato': {}}},
'Solanaceae': {'Solanum': {'potato': {},
'tomato': {}}}}}}
答案 0 :(得分:2)
对于你的问题的新版本(在你的评论中),你想要的是顶级字典的所有键,并且对于每一个键,相应的二级字典的所有键,以及第三次也是如此。
换句话说,您需要通过树的所有路径的列表,但在第三级截断。所以,让我们先在树上进行深度优先走,然后在第三层进行截断。
首先,让我们编写一个简单的深度优先路径查找器:
def paths(tree, path=()):
for key, subtree in tree.items():
if subtree:
yield from paths(subtree, path + (key,))
else:
yield path + (key,)
现在,让我们在深度3截断它:
def prefix_paths(prefix_length, tree, path=()):
for key, subtree in tree.items():
if subtree and len(path) + 1 < prefix_length:
yield from prefix_paths(prefix_length, subtree, path + (key,))
else:
yield path + (key,)
就是这样:
>>> results = list(prefix_paths(3, taxonomy))
>>> print(results)
[('Animalia', 'Chordata', 'Mammalia'),
('Plantae', 'Solanales', 'Solanaceae'),
('Plantae', 'Solanales', 'Convolvulaceae')]
实际上,您在评论中描述的内容是您需要前三个级别中所有键的单个元组。但是你可以从上面轻松搞定。只需将列表展平并消除重复:
>>> flatten = itertools.chain.from_iterable
>>> keys = flatten(prefix_paths(3, taxonomy))
>>> unique_keys = tuple(set(keys))
>>> print(unique_keys)
('Chordata', 'Convolvulaceae', 'Plantae', 'Solanales', 'Animalia', 'Mammalia', 'Solanaceae')
(顺便说一句,订单完全不确定,因为这就是字典的工作原理;我碰巧得到的评论与你的评论相同,这只是一个意外,你不应该依赖它......)
与此同时,这是我对问题原始版本的回答(这仍然是问题中的问题......)。
就是这样:
taxonomy['Animalia']['Chordata']['Mammalia']
或者,如果你想要“干净”版本:
dicts(taxonomy)['Animalia']['Chordata']['Mammalia']
或者,或者:
dicts(taxonomy['Animalia']['Chordata']['Mammalia'])
如果您愿意,可以编写包装函数。
如果您知道它总是有三个键:
def subtree(tree, three_keys):
return tree[three_keys[0]][three_keys[1]][three_keys[2]]
如果您希望它使用任意数量的键:
def subtree(tree, keys):
while keys:
tree, keys = tree[keys[0]], keys[1:]
return tree
然后:
subtree(taxonomy, ('Animalia', 'Chordata', 'Mammalia'))
同样,您可以将taxonomy
或整体结果传递给dicts
以获得“干净”版本。
以上所有内容均为您提供:
{'Carnivora': {'Canidae': {'Canis': {'dog': {}}},
''Felidae':{'Felis':{'cat':{}},'Panthera':{'lion':{}}}}}
(或其凌乱的defaultdict
等价物。)
如果你想让它变得更好:
pprint.pprint(subtree(dicts(taxonomy), ('Animalia', 'Chordata', 'Mammalia')))
...给你:
{'Carnivora': {'Canidae': {'Canis': {'dog': {}}},
'Felidae': {'Felis': {'cat': {}},
'Panthera': {'lion': {}}}}}}