Python 中的多级键和值

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17154393/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 00:37:48  来源:igfitidea点击:

Multiple levels of keys and values in Python

pythonpython-2.7dictionary

提问by Justin Carrey

I wanted to know if the functionality i am trying to implement in python is possible.

我想知道我尝试在 python 中实现的功能是否可行。

I have a global hash called Creatures. Creatures contain sub-hashes called mammals, amphibians, birds, insects.

我有一个名为 Creatures 的全局哈希。生物包含称为哺乳动物、两栖动物、鸟类、昆虫的子哈希。

Mammals have sub-hashes called whales, elephants. Amphibians have sub-hashes called frogs, larvae. Birds have sub-hashes called Eagle, parakeet. Insects have sub-hashes called dragonfly, mosquito.

哺乳动物有称为鲸鱼、大象的子哈希。两栖动物有称为青蛙,幼虫的子哈希。鸟类有称为鹰,长尾小鹦鹉的子哈希。昆虫有子哈希称为蜻蜓、蚊子。

Again, Eagles have sub-hashes called male, female.

同样,老鹰有称为男性,女性的子哈希。

I am counting the frequencies of all these creatures from a text file. For example, if the file is in below format:

我正在计算文本文件中所有这些生物的频率。例如,如果文件采用以下格式:

Birds   Eagle  Female
Mammals whales Male
Birds   Eagle  Female

I should output Creatures[Birds[Eagle[Female]]] = 2
                Creatures[mammals[Whales[Male]]] = 1  

Is it possible in Python? How can it be done? I am very new to Python and please help is much appreciated. I am comfortable with dictionaries only upto 1 level, i.e. key-> value. But here, there are multiple keys and multiple values. i am not sure how to proceed with this. I am using python 2.6. Thanks in advace!

在 Python 中可能吗?怎么做到呢?我对 Python 非常陌生,非常感谢您的帮助。我对最多 1 个级别的字典感到满意,即键-> 值。但在这里,有多个键和多个值。我不知道如何进行。我正在使用 python 2.6。先谢谢了!

采纳答案by Sylvain Leroux

If you just have to "count" things -- and assuming the data file contains all the required level of "hashes" -- that will do the trick:

如果您只需要“计算”事物——并假设数据文件包含所有必需的“哈希”级别——那就可以了:

import collections

result = collections.defaultdict(int)

with open("beast","rt") as f:
    for line in f:
        hashes = line.split()
        key = '-'.join(hashes)
        result[key] += 1

print result

Producing the result:
defaultdict(<type 'int'>, {'Mammals-whales-Male': 1, 'Birds-Eagle-Female': 2})

产生结果:
defaultdict(<type 'int'>, {'Mammals-whales-Male': 1, 'Birds-Eagle-Female': 2})

If you require nested dictionary -- post-processing of that result is still possible...

如果您需要嵌套字典 - 仍然可以对该结果进行后处理...

回答by chepner

The value assigned to a key in a dictionary can itself be another dictionary

分配给字典中键的值本身可以是另一个字典

creatures = dict()
creatures['birds'] = dict()
creatures['birds']['eagle'] = dict()
creatures['birds']['eagle']['female'] = 0
creatures['birds']['eagle']['female'] += 1

You need to explicitly create each dictionary, though. Unlike Perl, Python does not automatically create a dictionary when you attempt to treat the value of an unassigned key as such.

但是,您需要明确创建每个字典。与 Perl 不同,当您尝试将未分配的键的值视为此类时,Python 不会自动创建字典。

Unless, of course, you use a defaultdict:

当然,除非您使用defaultdict

from collections import defaultdict
creatures = defaultdict( lambda: defaultdict(lambda: defaultdict( int )))
creatures['birds']['eagle']['female'] += 1

For arbitrary levels of nesting, you can use this recursive definition

对于任意级别的嵌套,您可以使用此递归定义

dd = defaultdict( lambda: dd )
creatures = dd
creatures['birds']['eagle']['female'] = 0

In this case, you do need to explicitly initialize the integer value, since otherwise the value of creatures['birds']['eagle']['female']will be assumed to be another defaultdict:

在这种情况下,您确实需要显式初始化整数值,否则 的值creatures['birds']['eagle']['female']将被假定为 another defaultdict

>>> creatures = dd
>>> type(creatures['birds']['eagle']['female'])
<class 'collections.defaultdict'>

回答by J0HN

Not elegant, but working:

不优雅,但工作:

result = {}
for line in input_file.split("\n"):
    curdict = result
    values = line.split(" ")
    for item in values[:-1]:
        if item not in curdict:
            curdict[item] = {}
        curdict = curdict[item]
    last_item = values[-1]
    if last_item not in curdict:
        curdict[last_item] = 0
    curdict[last_item] += 1

This probably can be written in a cleaner way, but at least it works and allows for arbitrary nesting level, unless you have different nesting level for the same "entity" (e.g. Birds Eagle Femaleand Birds Eaglewon't work)

这可能可以用更简洁的方式编写,但至少它可以工作并允许任意嵌套级别,除非您对同一个“实体”有不同的嵌套级别(例如Birds Eagle Female并且Birds Eagle不起作用)