我正在创建一个嵌套的参考字典,以记录数据字典可能具有的所有可能键,并具有对应的值,这些值是将在平面字典中使用的所有键。

数据字典的键将始终是参考字典的键的子集。平面字典的键将始终是参考字典的值集的子集。

换句话说,给定参考字典,其分配如下:

reference['agent']['address'] = 'agentaddress'
reference['agent']['zone']['id'] = 'agentzoneid'
reference['eventid'] = 'eventid'
reference['file']['hash'] = 'filehash'
reference['file']['name'] = 'filename'


以及具有以下分配的数据字典:

nested['agent']['address'] = '172.16.16.16'
nested['eventid'] = '1234566778'
nested['file']['name'] = 'reallybadfile.exe'


代码应该产生一个字典,可以这样分配:

flat['agentaddress'] = '172.16.16.16'
flat['eventid'] = '1234566778'
flat['filename'] = 'reallybadfile.exe'


我永远无法知道嵌套字典中的哪些字段将被填充,而哪些字段不会被填充,但是我可以知道参考字典中的映射。

我希望我将需要使用递归将字典遍历为子字典,并可能使用某种间接方式分别从参考字典值和嵌套字典键创建平面字典键和值。

但是,我还无法生成任何有意义的代码。

也许从很高的角度来看,它看起来可能像这样:

def this(ref, nest, flat, *args):
    for (k,v) in reference:
        if type(v) is dict:
            this(?, ?, ?, ?)
        elif nested[path][to][k]:
            flat[reference[path][to][k]] = nested[path][to][k]


其中[path][to][k]表示某种间接方式,而*args是我要传递给递归函数的东西,这样我就可以拥有足够的上下文以遍历字典的嵌套来引用键和我需要的价值观。

最佳答案

使用generator,这很简单:

码:

def make_flat_tuples(data, ref):
    for k, v in data.items():
        if isinstance(v, dict):
            for x in make_flat_tuples(v, ref[k]):
                yield x
        else:
            yield ref[k], v

flat = dict(make_flat_tuples(nested, reference))


测试代码:

from collections import defaultdict

reference = defaultdict(dict)
reference['agent'] = defaultdict(dict)

reference['agent']['address'] = 'agentaddress'
reference['agent']['zone']['id'] = 'agentzoneid'
reference['eventid'] = 'eventid'
reference['file']['hash'] = 'filehash'
reference['file']['name'] = 'filename'

nested = defaultdict(dict)

nested['agent']['address'] = '172.16.16.16'
nested['eventid'] = '1234566778'
nested['file']['name'] = 'reallybadfile.exe'

print(dict(make_flat_tuples(nested, reference)))


结果:

{
    'agentaddress': '172.16.16.16',
    'eventid': '1234566778',
    'filename': 'reallybadfile.exe'
}

关于python - 如何从嵌套词典创建平面词典,该词典的键是引用词典的子集?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48030287/

10-09 16:41