【问题标题】:Copy nested dictionary to another dictionary with all the levels将嵌套字典复制到具有所有级别的另一个字典
【发布时间】:2019-08-06 17:51:10
【问题描述】:

对于某些第三方 API,API 参数中有大量数据需要发送。输入数据以 CSV 格式进入我们的应用程序。

我收到 CSV 的所有行,包含大约 120 列,由 CSV DictReader 以平面 dict 格式。

file_data_obj = csv.DictReader(open(file_path,  'rU'))

这给了我以下格式的每一行:

CSV_PARAMS = {
    'param7': "Param name",
    'param6': ["some name"],
    'param5': 1234,
    'param4': 999999999,
    'param3': "some ",
    'param2': {"x name":"y_value"},
    'param1': None,
    'paramA': "",
    'paramZ': 2.687
}

并且有一个嵌套字典,其中包含所有第三方 API 参数作为具有空白值的键。

eg. API_PARAMS = {
    "param1": "",
    "param2": "",
    "param3": "",
    "paramAZ": {
        "paramA": "",
        "paramZ": {"test1":1234, "name":{"hello":1}},
        ...
    },
    "param67": {
        "param6": "",
        "param7": ""
    },
    ...
  }

我必须将所有 CSV 值动态映射到 API 参数。以下代码有效,但最多只能嵌套 3 级。

def update_nested_params(self, paramdict, inpdict, result={}):
    """Iterate over nested dictionary up to level 3 """
    for k, v in paramdict.items():
        if isinstance(v, dict):
            for k1, v1 in v.items():
                if isinstance(v1, dict):
                    for k2, _ in v1.items():
                        result.update({k:{k1:{k2: inpdict.get(k2, '')}}})
                else:
                    result.update({k:{k1: inpdict.get(k1, '')}})
        else:
            result.update({k: inpdict.get(k, '')})
    return result




self.update_nested_params(API_PARAMS, CSV_PARAMS)

对于 API 参数的 n 次嵌套,是否有其他有效的方法来实现这一点?

【问题讨论】:

标签: python csv dictionary


【解决方案1】:

你可以使用递归:

def update_nested_params(self, template, source):
    result = {}
    for key, value in template.items():
        if key in source:
            result[key] = source[key]
        elif not isinstance(value, dict):
            # assume the template value is a default
            result[key] = value
        else:
            # recurse
            result[key] = self.update_nested_params(value, source)
    return result

这会递归地复制“模板”(API_PARAMS),如果可用,则从source 中获取它找到的任何键,如果没有,则递归,但template 中的值是另一个字典。这可以处理高达sys.getrecursionlimit() 级别的嵌套(默认为 1000)。

或者,使用显式堆栈:

# extra import to add at the module top
from collections import deque

def update_nested_params(self, template, source):
    top_level = {}
    stack = deque([(top_level, template)])
    while stack:
        result, template = stack.pop()
        for key, value in template.items():
            if key in source:
                result[key] = source[key]
            elif not isinstance(value, dict):
                # assume the template value is a default
                result[key] = value
            else:
                # push nested dict into the stack
                result[key] = {}
                stack.append((result[key], value))
    return top_level

这实际上只是将递归中使用的调用堆栈移动到显式堆栈。处理键的顺序从深度到呼吸首先发生变化,但这对您的具体问题无关紧要。

【讨论】:

    猜你喜欢
    • 2020-12-30
    • 1970-01-01
    • 1970-01-01
    • 2021-06-08
    • 2019-01-09
    • 2019-11-27
    • 1970-01-01
    • 2023-03-02
    • 1970-01-01
    相关资源
    最近更新 更多