代码片段-复杂结构字典merge

两个字典递归merge, 并打印出 merge过程中, 简单数据类型(非字典, 列表)被替换的节点

def dict_merge(dct, merge_dct, cur_section, error_list, error_prefix=""):
    """Recursive dict merge. Inspired by :meth:``dict.update()``, instead of
        updating only top-level keys, dict_merge recurses down into dicts nested
        to an arbitrary depth, updating keys. The ``merge_dct`` is merged into
        ``dct``.
        :param dct: dict onto which the merge is executed
        :param merge_dct: dct merged into dct
        :param cur_section: 记录当前比较到的节点位置
        :param error_list: merge 过程中的冲突
        :param error_prefix: 错误信息的前缀
        :return: None
        """
    for k, v in merge_dct.iteritems():

        if k in dct:

            if isinstance(dct[k], dict) and isinstance(merge_dct[k], dict):

                if cur_section:
                    cur_section.append(k)
                else:
                    cur_section = [k]

                dict_merge(dct[k], merge_dct[k], cur_section, error_list, error_prefix=error_prefix)

            elif isinstance(dct[k], (list, tuple)) and isinstance(v, (list, tuple)):

                if cur_section:
                    cur_section.append(k)
                else:
                    cur_section = [k]

                temp_list = cur_section[:]
                temp_list.reverse()

                lasted_index = len(temp_list) - temp_list.index(k)

                for index, arr_item in enumerate(dct[k]):
                    if isinstance(arr_item, dict) and isinstance(v[index], dict):
                        if cur_section:
                            cur_section.append(str(index))
                        else:
                            cur_section = [str(index)]

                        dict_merge(arr_item, v[index], cur_section, error_list, error_prefix=error_prefix)

                    cur_section = cur_section[:lasted_index]

            elif dct[k] != v:
                print("warninig...", k, dct[k], v)

                err_data = {
                    "error_prefix": error_prefix,
                    "section": ".".join(cur_section) + "." + k,
                    # "section": [k],
                    "origin_data": dct[k],
                    "merge_data": merge_dct[k]
                }
                error_list.append(err_data)
                dct[k] = merge_dct[k]

        else:
            dct[k] = merge_dct[k]

        if k in cur_section:
            temp_list = cur_section[:]
            temp_list.reverse()

            lasted_index = len(temp_list) - temp_list.index(k) - 1  # 需要把当前这层也去掉

            cur_section = cur_section[:lasted_index]


def run_dict_merge():
    import pprint
    dct = {'interstitial_ad_plan': None,
           'reward_ad_plan': None,
           'promotion_plan': None,
           'Module': {'Commands': {'OpenRookie': {'CornerDict': {'Priority': 500,
                                                                 'resourceName': 'RokieButton',
                                                                 'ChannelName': 'Channel_0'},
                                                  'showCount': 1000,
                                                  'Interval': 0,
                                                  'Priority': 800,
                                                  'eventDict': {'event': 'OpenRookie'},
                                                  'Conditions': [{'ConditionType': 'EventCondition',
                                                                  'R': 'OpenRookie',
                                                                  'Description': 'GeneralEvent',
                                                                  'ConditionContent': {'IsRookieOnlyBuyOnce': True,
                                                                                       'FirstCoolDownGlobalSpinCountInterval': 2000,
                                                                                       'TriggerMoment': 'SpinEnd',
                                                                                       'PopUpSuspend': True,
                                                                                       'SwitchOn': True},
                                                                  'ConditionName': 'AfterSpinClicked'},
                                                                 {'ConditionType': 'EventCondition',
                                                                  'R': 'OpenRookie',
                                                                  'Description': 'RookieOfferEvent',
                                                                  'ConditionContent': {'IsRookieOnlyBuyOnce': True,
                                                                                       'Probality': '1,3',
                                                                                       'TriggerMoment': 'BackToLobby',
                                                                                       'SwitchOn': True},
                                                                  'ConditionName': 'BackToLobby'},
                                                                 {'ConditionType': 'EventCondition',
                                                                  'R': 'OpenRookie',
                                                                  'Description': 'RookieOfferEvent',
                                                                  'ConditionContent': {'IsRookieOnlyBuyOnce': True,
                                                                                       'TriggerMoment': 'EnterLobby'},
                                                                  'ConditionName': 'LobbyOpenRookie'},
                                                                 {'ConditionType': 'EventCondition',
                                                                  'R': 'OpenRookie',
                                                                  'Description': 'RookieOfferEvent',
                                                                  'ConditionContent': {'IsRookieOnlyBuyOnce': True,
                                                                                       'Probality': '2,2',
                                                                                       'TriggerMoment': 'CloseShop'},
                                                                  'ConditionName': 'CloseShopRookie'},
                                                                 {'ConditionType': 'EventCondition',
                                                                  'R': 'OpenRookie',
                                                                  'Description': 'RookieOfferEvent',
                                                                  'ConditionContent': {'IsRookieOnlyBuyOnce': True,
                                                                                       'Probality': '3,10',
                                                                                       'TriggerMoment': 'CloseBigWin'},
                                                                  'ConditionName': 'MachineBigWinRookie'},
                                                                 {'ConditionName': 'MachineOutofCoinsRookie',
                                                                  'ConditionType': 'EventCondition',
                                                                  'R': 'OpenRookie',
                                                                  'ConditionContent': {'IsRookieOnlyBuyOnce': True,
                                                                                       'Probality': '4,4',
                                                                                       'TriggerMoment': 'CloseOutOfCoins'},
                                                                  'Desacription': 'RookieOfferEvent'}],
                                                  'type': 'eventCmd'}}},
           'store_plan': None}

    merge_dct = {'interstitial_ad_plan': None,
                 'reward_ad_plan': None,
                 'promotion_plan': None,
                 'Module': {'Commands': {'OpenRookie': {'eventDict': {'event': 'OpenRookie'},
                                                        'showCount': 1200,
                                                        'Interval': 0,
                                                        'Priority': 1800,
                                                        'CornerDict': {'Priority': 5600,
                                                                       'resourceName': 'RokieButton',
                                                                       'ChannelName': 'Channel_0'},
                                                        'type': 'eventCmd',
                                                        'Conditions': [{'ConditionType': 'EventCondition',
                                                                        'R': 'OpenRookie',
                                                                        'Description': 'GeneralEvent',
                                                                        'ConditionContent': {
                                                                            'IsRookieOnlyBuyOnce': True,
                                                                            'FirstCoolDownGlobalSpinCountInterval': 2000,
                                                                            'TriggerMoment': 'SpinEnd',
                                                                            'PopUpSuspend': False,
                                                                            'SwitchOn': True},
                                                                        'ConditionName': 'AfterSpinClicked'},
                                                                       {'ConditionType': 'EventCondition',
                                                                        'R': 'OpenRookie',
                                                                        'Description': 'RookieOfferEvent',
                                                                        'ConditionContent': {
                                                                            'IsRookieOnlyBuyOnce': True,
                                                                            'Probality': '1,3',
                                                                            'TriggerMoment': 'BackToLobby',
                                                                            'SwitchOn': True},
                                                                        'ConditionName': 'BackToLobby'},
                                                                       {'ConditionType': 'EventCondition',
                                                                        'R': 'OpenRookie',
                                                                        'Description': 'RookieOfferEvent',
                                                                        'ConditionContent': {
                                                                            'IsRookieOnlyBuyOnce': True,
                                                                            'TriggerMoment': 'EnterLobby'},
                                                                        'ConditionName': 'LobbyOpenRookie'},
                                                                       {'ConditionType': 'EventCondition',
                                                                        'R': 'OpenRookie',
                                                                        'Description': 'RookieOfferEvent',
                                                                        'ConditionContent': {
                                                                            'IsRookieOnlyBuyOnce': True,
                                                                            'Probality': '2,3',
                                                                            'TriggerMoment': 'CloseShop'},
                                                                        'ConditionName': 'CloseShopRookie'},
                                                                       {'ConditionType': 'EventCondition',
                                                                        'R': 'OpenRookie',
                                                                        'Description': 'RookieOfferEvent',
                                                                        'ConditionContent': {
                                                                            'IsRookieOnlyBuyOnce': True,
                                                                            'Probality': '3,10',
                                                                            'TriggerMoment': 'CloseBigWin'},
                                                                        'ConditionName': 'MachineBigWinRookie'},
                                                                       {'R': 'OpenRookie',
                                                                        'ConditionType': 'EventCondition',
                                                                        'Desacription': 'RookieOfferEvent',
                                                                        'ConditionContent': {
                                                                            'IsRookieOnlyBuyOnce': True,
                                                                            'Probality': '4,4',
                                                                            'TriggerMoment': 'CloseOutOfCoins'},
                                                                        'ConditionName': 'MachineOutofCoinsRookie'}]}}},
                 'store_plan': None}

    cur_section = []
    error_list = []

    dict_merge(dct, merge_dct, cur_section, error_list)
    print(cur_section)
    pprint.pprint(error_list)

执行结果


('warninig...', 'Priority', 500, 5600)
('warninig...', 'showCount', 1000, 1200)
('warninig...', 'Priority', 800, 1800)
('warninig...', 'PopUpSuspend', True, False)
('warninig...', 'Probality', '2,2', '2,3')


[]   # cur_section 已经是空的了

[{'error_prefix': '',
  'merge_data': 5600,
  'origin_data': 500,
  'section': 'Module.Commands.OpenRookie.CornerDict.Priority'},
 {'error_prefix': '',
  'merge_data': 1200,
  'origin_data': 1000,
  'section': 'Module.Commands.OpenRookie.showCount'},
 {'error_prefix': '',
  'merge_data': 1800,
  'origin_data': 800,
  'section': 'Module.Commands.OpenRookie.Priority'},
 {'error_prefix': '',
  'merge_data': False,
  'origin_data': True,
  'section': 'Module.Commands.OpenRookie.Conditions.0.ConditionContent.PopUpSuspend'},
 {'error_prefix': '',
  'merge_data': '2,3',
  'origin_data': '2,2',
  'section': 'Module.Commands.OpenRookie.Conditions.3.ConditionContent.Probality'}]
posted @ 2020-06-29 11:41  张璨  阅读(123)  评论(0)    收藏  举报