字典和嵌套字典之间的 Python 键匹配并将新值写入嵌套字典

时间:2021-01-13 16:52:14

标签: python

我有两个字典,一个是标准的键/值对字典,另一个是嵌套的 OrderedDict,具有标准字典的公共键名,但有空值。

我正在寻找一种方法来从标准键/值字典 (properties_dict) 中提取值并将这些值放入我的键匹配的嵌套字典 (blank_dict) 中。

我已经研究过使用“isinstance”来迭代形成其他列表/字典的值,但现在我开始怀疑我是否走错了路并且可能使它过于复杂。我遇到的另一个问题是一个值 'Variant' 是列表形式,因此我正在寻找一种方法来在遍历 OrderedDict 时将每个值从列表中弹出。

我在下面添加了我的尝试。

from collections import OrderedDict


def walkdicts(blankdict, propsdict):
    for k, v in blankdict.items():
        for k2, v2 in propsdict.items():
            if k == k2:
                blankdict[k] = v2
        if isinstance(v, dict):
            walkdicts(v, propsdict)
        elif isinstance(v, list):
            for i in v:
                walkdicts(i[0], propsdict)

    return blankdict


properties_dict = {'A_ID': '2702',
 'Sys': 'MySystem',
 'Namespace': 'SomeNamespace',
 'Vers': '112A',
 'Variant': ['1','2'],
 'SpecID': 'Target1',
 'Seq': '12345',
 'Match': 'ABCDEFG',
 'Time': '200',
 'Case1': 'A',
 'Type': 'Include',
 'MyRef': '1010',
 'Case2': 'B'}


blank_dict =   OrderedDict([('Main', OrderedDict([
                    ('Vers', ''), 
                    ('Namespace', ''), 
                    ('Sys', ''), 
                    ('A_ID', ''),
                    ('Variant', '1'),
                ('Sec1', OrderedDict([
                    ('RequestID', OrderedDict([
                        ('Case1', ''), 
                        ('Case2', '')])), 
                    ('Variant', ''), 
                    ('MyRef', '')])), 
                ('Sec2', OrderedDict([
                    ('UHD', OrderedDict([
                        ('SpecID', ''), 
                        ('Type', ''), 
                        ('AD2W', OrderedDict([
                            ('Time', ''), 
                            ('Match', ''), 
                            ('Seq', '')]))]))]))]))])


new_dict = walkdicts(blank_dict, properties_dict)

print(new_dict)

这是我正在寻找的输出 Ordered 字典:

    new_dict =   OrderedDict([('Main', OrderedDict([
                    ('Vers', '112A'), 
                    ('Namespace', 'SomeNamespace'), 
                    ('Sys', 'MySystem'), 
                    ('A_ID', '2702'),
                    ('Variant', '1'),
                ('Sec1', OrderedDict([
                    ('RequestID', OrderedDict([
                        ('Case1', 'A'), 
                        ('Case2', 'B')])), 
                    ('Variant', '2'), 
                    ('MyRef', '1010')])), 
                ('Sec2', OrderedDict([
                    ('UHD', OrderedDict([
                        ('SpecID', 'Target1'), 
                        ('Type', 'Include'), 
                        ('AD2W', OrderedDict([
                            ('Time', '200'), 
                            ('Match', 'ABCDEFG'), 
                            ('Seq', '12345')]))]))]))]))])

感谢您的时间。

1 个答案:

答案 0 :(得分:1)

这是一个函数,它返回一个嵌套的 OrderedDict,它与 template 中的结构匹配,并通过在 props 中执行查找来填充值:

def populate(template, props, prop_indexes=None):
    if prop_indexes is None:
        prop_indexes = {}
    result = OrderedDict()
    for k, v in template.items():
        if isinstance(v, dict):
            result[k] = populate(v, props, prop_indexes)
            continue
        if k in props.keys():
            if isinstance(props[k], list):
                if k not in prop_indexes:
                    prop_indexes[k] = 0
                index = prop_indexes[k] % len(props[k])
                result[k] = props[k][index]
                prop_indexes[k] += 1
            else:
                result[k] = props[k]
    return result

一些注意事项:

  • prop_indexes 用于跟踪定义为值列表的每个属性的位置。使用模数 (%) 运算符,如果 target 中的实例多于列表中的值,我们可以重复循环遍历列表
  • 由于 props 是字典,因此无需遍历它。相反,只需检查密钥是否存在。
  • 这仍然可以使用一些工作来优雅地处理边缘情况和错误情况,但我只是想演示一种工作方法。一个主要假设是 template 仅包含嵌套字典。

使用 blank_dict 的定义(通过添加额外的 Variant 键稍微修改,请参阅输出后的注释)和示例代码中的 properties_dict,这里有一小段代码把它们放在一起:

import pprint
pp = pprint.PrettyPrinter()

print("## blank_dict ##")
pp.pprint(blank_dict)

new_dict = populate_new(blank_dict, properties_dict)

print("## new_dict ##")
pp.pprint(new_dict)

这是输出(pprint 并没有真正将 OrderedDict 渲染得那么漂亮,但它完成了工作):

## blank_dict ##
OrderedDict([('Main',
              OrderedDict([('Vers', ''),
                           ('Namespace', ''),
                           ('Sys', ''),
                           ('A_ID', ''),
                           ('Variant', ''),
                           ('Sec1',
                            OrderedDict([('RequestID',
                                          OrderedDict([('Case1', ''),
                                                       ('Case2', '')])),
                                         ('Variant', ''),
                                         ('MyRef', '')])),
                           ('Sec2',
                            OrderedDict([('UHD',
                                          OrderedDict([('SpecID', ''),
                                                       ('Type', ''),
                                                       ('Variant', ''),
                                                       ('AD2W',
                                                        OrderedDict([('Time',
                                                                      ''),
                                                                     ('Match',
                                                                      ''),
                                                                     ('Seq',
                                                                      '')]))]))]))]))])
## new_dict ##
OrderedDict([('Main',
              OrderedDict([('Vers', '112A'),
                           ('Namespace', 'SomeNamespace'),
                           ('Sys', 'MySystem'),
                           ('A_ID', '2702'),
                           ('Variant', '1'),
                           ('Sec1',
                            OrderedDict([('RequestID',
                                          OrderedDict([('Case1', 'A'),
                                                       ('Case2', 'B')])),
                                         ('Variant', '2'),
                                         ('MyRef', '1010')])),
                           ('Sec2',
                            OrderedDict([('UHD',
                                          OrderedDict([('SpecID', 'Target1'),
                                                       ('Type', 'Include'),
                                                       ('Variant', '1'),
                                                       ('AD2W',
                                                        OrderedDict([('Time',
                                                                      '200'),
                                                                     ('Match',
                                                                      'ABCDEFG'),
                                                                     ('Seq',
                                                                      '12345')]))]))]))]))])

注意:我添加了一个额外的 Variant 实例来演示填充 3 个实例,即使 properties_dict 中只指定了 2 个值