【问题标题】:How do you combine two similar nested dictionaries into one, each with some shared and unique nested elements (Python)?如何将两个相似的嵌套字典合二为一,每个字典都有一些共享且唯一的嵌套元素(Python)?
【发布时间】:2018-06-01 13:53:46
【问题描述】:

我有两个大型嵌套字典需要合并成一个:

dict1={
1: {"trait1: 32", "trait2": 43, "trait 3": 98},
2: {"trait1: 38", "trait2": 40, "trait 3": 95},
....
}

dict2={
1: {"trait1: 32", "trait2": 43, "trait 4": 54},
2: {"trait1: 38", "trait2": 40, "trait 4": 56},
....
}

而我想得到的是这样的:

dict3={
1: {"trait1: 32", "trait2": 43, "trait 3": 98, "trait 4": 54},
2: {"trait1: 38", "trait2": 40, "trait 3": 95, "trait 4": 56},
....
}

我尝试过使用:

dict3=dict(list(dict1.items()) + list(dict2.items()))

但它只是为我复制 dict2。

我也尝试过像这样循环遍历“主”键(我复制了第一个字典成为最终输出):

dict3 = dict(dict1)

for key1 in dict3:
    for key2 in dict2:
        dict3[key1].update({"trait4": dict2[key2]["trait4"]})

但这不起作用,只有每隔几个条目会按预期在输出中出现。我相当肯定我的方法在这方面是错误的。任何帮助表示赞赏!

【问题讨论】:

    标签: python python-3.x dictionary nested


    【解决方案1】:

    要实现您的目标,您所要做的就是检查字典是否包含键。您应该定义一个函数,例如 update_keys(),它将接受两个参数:dict1dict2

    要检查dictionary 是否有key,只需编写(如this question 中所述):

    if key in dictionary:
        # Action you want to take if dictionary has key.
    

    因此,您的解决方案将如下所示(请注意,deepcopy 函数是从复制模块导入的,如下面的更新 1 中所述):

    #!/usr/bin/env python3
    
    from copy import deepcopy
    
    def update_keys(dict1, dict2):
        result_dict = deepcopy(dict1)
        for key in dict2:
            if key in result_dict:
                for sub_key in dict2[key]:
                    result_dict[key].update({sub_key: dict2[key][sub_key]})
            else: 
                result_dict.update({key: dict2[key]})
        return result_dict
    
    dict3 = update_keys(dict1, dict2)
    

    另外为了澄清一些事情,您可以使用 dictionary.items() 来迭代使用值,就像在 this question 中提到的那样,因为在嵌套循环和多个 if 语句中,您可能会在所有变量之间迷失。

    #!/usr/bin/env python3
    
    from copy import deepcopy
    
    dict1={
    1: {"trait1": 32, "trait2": 43, "trait3": 98},
    2: {"trait1": 38, "trait2": 40, "trait3": 95}
    }
    
    dict2={
    1: {"trait1": 32, "trait2": 43, "trait4": 54},
    2: {"trait1": 38, "trait2": 40, "trait4": 56}
    }
    
    def update_keys(dict_one, dict_two):
        result_dict = deepcopy(dict_one)
        for key, value in dict_two.items():
            if key in result_dict:
                for sub_key, sub_value in value.items():
                    if sub_key not in result_dict[key]:
                        result_dict[key].update({sub_key: sub_value})
            else:
                result_dict.update({key: value})
        return result_dict
    
    dict3 = update_keys(dict1, dict2)
    

    更新 1: 感谢@shash678,我可以改进我的答案。如question topic 中所述,较早将字典传递给方法并通过分配新值创建浅拷贝来进行复制。因此,如果要保留dict1,则需要导入copy 模块并从中使用deepcopy() 函数。感谢@shash678,这个答案在不修改dict1的情况下完成了它的工作。

    【讨论】:

    • @shash678 谢谢你的注意,愚蠢的错误……我更新了代码。
    • @Stranger1750 请阅读[如果有人回答该怎么办] (stackoverflow.com/help/someone-answers) 的指南。它说评论的目的是要求澄清,留下建设性的批评,或添加相关但次要的附加信息——而不是社交。
    • @shash678 你对这个答案做了很大的改进,但是我决定在函数定义中使用copy.deepcopy(),而不是在函数调用期间使用参数。
    【解决方案2】:

    如果可以假设两个字典中的键相同(对于 python 3.5+),我想提出一个非常方便的合并。如果键都相同,我们可以简单地这样做:

    merged_dict = {}
    for key in dict1.keys():
        merged_dict[key] = {**dict1[key], **dict2[key]}
    # result: 
    # merged_dict is {1: {'trait1': 32, 'trait2': 43, 'trait3': 98, 'trait4': 54},
    #                 2: {'trait1': 38, 'trait2': 40, 'trait3': 95, 'trait4': 56}}
    

    dict 前面的双星将其解包,从 Python 3.5 开始,这种语法将允许我们在 dict 文字中解包 dict,从而有效地合并它们。我在这里假设原始字典的每个值都是字典本身。您可以通过某种方式直接对嵌套的字典进行解包(而不是使用 for 循环),但我不知道如何(如果有人这样做,请发表评论!)。

    如果我们假设键可能不同,我们必须添加一些东西,但没有嵌套结构,所以我认为它仍然很简单。例如,假设 dict2 有一个键/值对 {3: {'trait5': 435, 'trait7': 42}}。

    # find the shared keys, i.e. the intersection of the key sets
    shared_keys = set(dict1.keys()).intersection(set(dict2.keys()))
    merged_dict = {}
    for key in shared_keys:
        merged_dict[key] = {**dict1[key], **dict2[key]}
    # now add any key/value pairs only in dict1
    for key in set(dict1.keys()) - shared_keys:
        merged_dict[key] = {**dict1[key]}
    # and the same for dict2
    for key in set(dict2.keys()) - shared_keys:
        merged_dict[key] = {**dict2[key]}
    # result:
    # merged_dict is {1: {'trait1': 32, 'trait2': 43, 'trait3': 98, 'trait4': 54}, 
    #                 2: {'trait1': 38, 'trait2': 40, 'trait3': 95, 'trait4': 56}},
    #                 3: {'trait5': 435, 'trait7': 42}}
    

    我使用集合操作来获取共享密钥,然后只在 dict1 和 dict2 中获取密钥。例如{1,2,3}和{1,2}的交集是{1,2},集合差{1,2,3} - {1,2} = {3}。

    我希望它足够清楚!

    【讨论】:

      【解决方案3】:
      def merge_dict(x,y):
          keys = list(set(x.keys() + y.keys()))
          result = {}
          for key in keys:
              if key in x.keys():
                  z = x[key].copy()
                  if key in y.keys():
                      z.update(y[key])
                  result[key] = z
              else:
                  result[key] = y[key]
              result[k] = z
          return result
      
      
      dict3 = merge_dict(dict1,dict2)
      

      【讨论】:

        猜你喜欢
        • 2019-04-06
        • 2019-01-09
        • 1970-01-01
        • 2021-03-14
        • 2020-07-29
        • 1970-01-01
        • 2023-03-07
        • 1970-01-01
        • 2012-02-10
        相关资源
        最近更新 更多