【问题标题】:How merge with appending two nested dictionaries in python?如何与在 python 中附加两个嵌套字典合并?
【发布时间】:2013-07-25 12:22:59
【问题描述】:

例如我有两个字典:

schema = {
    'type': 'object',
    'properties': {
        'reseller_name': {
            'type': 'string',
        },
        'timestamp': {
            'type': 'integer',
        },
    },
    'required': ['reseller_name', 'timestamp'],
}

schema_add = {
    'properties': {
        'user_login': {
            'type': 'string',
        },
    },
    'required': ['user_login'],
}

我如何才能将下一个与附加结果字典合并:

schema_result = {
    'type': 'object',
    'properties': {
        'reseller_name': {
            'type': 'string',
        },
        'timestamp': {
            'type': 'integer',
        },
        'user_login': {
            'type': 'string',
        },
    },
    'required': ['reseller_name', 'timestamp', 'user_login'],
}

规则:

在示例中,schemescheme_add 的路径是 propertiesrequired

  1. 如果两个 dict 具有相同路径的 dict,则它们以相同的规则合并。
  2. 如果两个字典都有相同路径的列表,则添加第一个列表和第二个。
  3. 如果两个 dict 具有相同路径的简单值(或 dict 和非 dict 或列表和非列表),则第一个值覆盖第二个值。
  4. 如果只有一个 dict 具有某个路径的键,则设置此键和值。

【问题讨论】:

  • 您似乎已经回答了自己的问题。您列出的规则您的答案。您在实施时遇到困难吗?如果是这样,您遇到了什么具体问题?
  • 在我列出规则之前看起来很难。现在有了@Nicolas78 的帮助,我做到了。

标签: python dictionary


【解决方案1】:

不确定问题出在哪里,但你写它的方式几乎就像一个计算机程序,示例就像一个测试用例。为什么不从这里开始呢?

def add_dict(d1, d2):
    newdict = {}
    for (key, value) in d1.iteritems():
        if key in d2: ...
            #apply rules, add to newdict, use 
        else:
            #simply add
    for (key, value) in d2.iteritems():
        if not key in d1:
            # simply add
    return newdict

这可能写得更紧凑,但可能更容易编辑。

编辑..写完最后一条评论,忍不住写了一个更好的实现

def merge_values(a,b):
    if a==None or b==None:
        return a or b
    # now handle cases where both have values
    if type(a)==dict:
        return add_dict(a, b)
    if type(a)==list:
        ...

def add_dict(d1,d2):
    return dict(
        [
            (key,
             merge_values(
                 d1.get(key,None),
                 d2.get(key,None)))
            for key
            in set(d1.keys()).union(d2.keys())
        ])

【讨论】:

    【解决方案2】:

    我自己的解决方案 @Nicolas78 帮助:

    def merge(obj_1, obj_2):
        if type(obj_1) == dict and type(obj_2) == dict:
            result = {}
            for key, value in obj_1.iteritems():
                if key not in obj_2:
                    result[key] = value
                else:
                    result[key] = merge(value, obj_2[key])
            for key, value in obj_2.iteritems():
                if key not in obj_1:
                    result[key] = value
            return result
        if type(obj_1) == list and type(obj_2) == list:
            return obj_1 + obj_2
        return obj_2
    

    【讨论】:

    • 如果你设置了result = dict(obj_2),那么你可以删除整个第二个for循环。
    • result = obj_2.copy() 更快
    • 啊,我现在才注意到你是提问者。
    • 使用if type(obj_1) == dict 测试类型通常是个坏主意,因为这会排除 dict 的子类。通常最好使用if isinstance(obj1, dict)
    【解决方案3】:

    我正在添加这个问题的简单解决方案。假设样本数据不会改变。

    def merge_nested_dicts(schema,schema_add):
        new_schema = schema
        for k in schema:
            if k in schema_add.keys():
                if isinstance(schema_add[k],dict):
                    new_schema[k].update(schema_add[k])
                if isinstance(schema_add[k],list):
                    new_schema[k] = new_schema[k]+schema_add[k]
        return new_schema
    

    【讨论】:

      【解决方案4】:

      如果您确切知道密钥,请尝试此操作。

      schema['properties'].update(schema_add['properties'])
      schema['result'].append(schema_add['result'])
      

      结果被合并到架构中。

      如果您不确切知道键,则需要一个循环来查找内部列表和字典。

      for value in schema:
          if value is dict:
              if schema_add.has_key(value) and schema_add[value] is dict:
                  schema[value].update(schema_add[value])
          elif value is list:
              if schema_add.has_key(value) and schema_add[value] is list:
                  schema[value].append(schema_add[value])
      

      结果也可以合并到不同的字典中。

      【讨论】:

        猜你喜欢
        • 2012-09-20
        • 1970-01-01
        • 2020-04-27
        • 2023-03-07
        • 2021-04-03
        • 2020-11-28
        • 1970-01-01
        • 2022-01-19
        • 1970-01-01
        相关资源
        最近更新 更多