在同一个lin中引用单独的dict

2024-06-02 16:35:24 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在使用这个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']

然后将其转换成dict进行漂亮的打印:

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': {}}}}}}

Tags: treereturndefcattaxonomyfelislioncanis
1条回答
网友
1楼 · 发布于 2024-06-02 16:35:24

对于问题的新版本(在您的评论中),您需要的是顶级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,)

就这样:

>>> 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': {}}},

“猫科动物”:{“猫科动物”:{}},“豹科动物”:{“狮子”:{}}}

(或其混乱的defaultdict等价物)。你知道吗

如果你想让它变得更好:

pprint.pprint(subtree(dicts(taxonomy), ('Animalia', 'Chordata', 'Mammalia')))

…这给了你:

{'Carnivora': {'Canidae': {'Canis': {'dog': {}}},
               'Felidae': {'Felis': {'cat': {}},
                           'Panthera': {'lion': {}}}}}}

相关问题 更多 >