Python 引用单行树中的单个DICT
我正在使用这一行树轻松地从excel中获取信息。以下是站点中的树示例:Python 引用单行树中的单个DICT,python,list,dictionary,tree,key,Python,List,Dictionary,Tree,Key,我正在使用这一行树轻松地从excel中获取信息。以下是站点中的树示例: def tree(): return defaultdict(tree) taxonomy = tree() taxonomy['Animalia']['Chordata']['Mammalia']['Carnivora']['Felidae']['Felis']['cat'] taxonomy['Animalia']['Chordata']['Mammalia']['Carnivora']['Felidae']['Pant
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')
的
对于问题的新版本(在您的评论中),您需要的是顶级dict的所有键,对于每一个,对应的第二级dict的所有键,对于第三级dict同样 换句话说,您需要一个通过树的所有路径的列表,但在第三级被截断。那么,让我们先做一个深度优先遍历树,然后在第三层截断 首先,让我们编写一个简单的深度优先路径查找程序:
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,)
实际上,您在注释中描述的是,您需要一个包含前三个级别中所有键的元组。但是你可以很容易地从上面得到。只需展平列表并消除重复项:
>>> 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'])
如果愿意,可以编写包装器函数 如果你知道它总是有三个键:
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
然后:
同样,您可以将taxonomy
或整体结果传递给dicts
,以获得“干净”版本
以上所有内容都为您提供了:
{'Carnivora': {'Canidae': {'Canis': {'dog': {}}},
猫科动物:{'Felis':{'cat':{},'Panthera':{'lion':{}
(或其凌乱的defaultdict
等价物)
如果您想让它变得更好:
pprint.pprint(subtree(dicts(taxonomy), ('Animalia', 'Chordata', 'Mammalia')))
…这给了你:
{'Carnivora': {'Canidae': {'Canis': {'dog': {}}},
'Felidae': {'Felis': {'cat': {}},
'Panthera': {'lion': {}}}}}}
对不起,我不清楚。我的意思是我希望所有可能的键都是列表格式。所以最后的列表是:('Plantae','Solanales','convalvaceae','Animalia','Chordata','malemalia')实际上,我想我可能可以将我拥有的树转换成子树,并使用类似于:def dicts(t):return{k:dicts(t[k])的结构来表示t}中的k除了使用def将前三层键返回到列表中之外……我只是随口说说而已。非常感谢!我在问你第二个答案!工作很棒。为了澄清,你说的“第二个答案”是指前3个级别中唯一键的扁平列表:
(“脊索动物”、“旋花科”、“植物”、“茄属”、“动物”、“哺乳动物”、“茄科”)
,对吧?不管怎样,只要你有问题,都可以作为将来的参考“对于一个列表或dict,我会迭代项目和_____;,但是对于一个树我该怎么做呢?”,答案通常与“深度优先遍历节点和_____;密切相关。因此,您可能需要使用几种不同的方法编写深度优先遍历(迭代与递归、生成器与列表返回函数等)巩固你头脑中的想法。文章的编辑版本仍然完全不清楚。原始版本似乎要求单独的子部分。从你的评论来看,这不是你想要的,但是你编辑的问题明确地说这正是你想要的。我试着编辑我的答案来处理所有的问题你似乎已经问过了,但在你弄清楚你问的是哪一个之前,没有人可能会重新打开你的问题。@abarnert我又编辑了一遍。希望现在能更清楚。
subtree(taxonomy, ('Animalia', 'Chordata', 'Mammalia'))
{'Carnivora': {'Canidae': {'Canis': {'dog': {}}},
pprint.pprint(subtree(dicts(taxonomy), ('Animalia', 'Chordata', 'Mammalia')))
{'Carnivora': {'Canidae': {'Canis': {'dog': {}}},
'Felidae': {'Felis': {'cat': {}},
'Panthera': {'lion': {}}}}}}