根据一个字典中的结构(骨架)创建嵌套字典,并从另一个字典

时间:2018-03-05 17:18:33

标签: python python-3.x dictionary

假设我有一个字典dict1,它有我想要的新词典的骨架(顺序和嵌套深度)。例如:

dict1 = {
   "Personnel": {
      "Performance": ""
   },
   "Gaming": {
      "Status": "",
      "Bug Status": ""
   },
   "Compatible": {
      "Minimum": "",
      "Integrity": "",
      "Scaling": ""
   },
   "Comparison": {
      "Difference": {
         "DirectX": ""
      },
      "Vendor": {
         "Intel": "",
         "Xiaomi": ""
      }
   }
}

我正在使用另一个字典dict2,其中的值与上面的dict1字典中的键对应,还有一些其他键值对:

dict2 = {
   "Personnel": {
      "Performance": "10.5",
      "Maximum": "50.5"
   },
   "Gaming": {
      "Status": "Cool",
      "Bug Status": "None",
      "Green Status": "Black"
   },
   "Compatible": {
      "Minimum": "5",
      "Integrity": "Yes",
      "Scaling": "No"
   },
   "Comparison": {
      "Difference": {
         "DirectX": "50",
         "Android": "70"
      },
      "Vendor": {
         "Xiaomi": "40"
      }
   },
   "Another property": {
      "Testinfo": "TestTest",
      "Important": {
         "Wow": "MuchDoge"
      }
   }
}

我想创建一个新词典,其中包含dict1的骨架以及从dict2获取的相应键值。

注意:我想跳过不属于dict1部分的键:值对。例如:我的新词典中不需要'Green Status': 'Black'

以下是我尝试的代码:

def update(dict1 : dict, dict2: dict):  
    new_data = {}
    for k, v in dict1.items():
        if isinstance(v, dict):
            v = update(v, dict(dict2.keys()))
        if v not in dict2.keys():
            new_data[k] = v
    return new_data

但我完全错过了一些东西。

2 个答案:

答案 0 :(得分:2)

您可以使用嵌套字典理解来实现此目的。在dict1.items()上迭代以获得(key, value)对的typle。再次从先前的操作迭代value dict以获取嵌套的新dict所需的密钥。然后,从dict2获取密钥的相应值。例如:

new_dict = {k: {v_k: dict2[k][v_k] for v_k in v_dict} for k, v_dict in dict1.items() }

如果dict.get('some_key')密钥不存在,最好使用some_key来处理异常。因此,上面的字典理解表达式将成为:

new_dict = {k: {v_k: dict2.get(k, {}).get(v_k) for v_k in v_dict} for k, v_dict in dict1.items() }

如果None中没有来自dict1的任何密钥,则会将dict2存储为值。

对于您的示例数据,上面的代码将返回new_dict

{
   "Compatible": {
      "Scaling": "No",
      "Minimum": "5",
      "Integrity": "Yes"
   },
   "Personnel": {
      "Performance": "10.5"
   },
   "Gaming": {
      "Status": "Cool",
      "Bug Status": "None"
   },
   "Comparison": {
      "Difference": {
         "Android": "70",
         "DirectX": "50"
      },
      "Vendor": {
         "Xiaomi": "40"
      }
   }
}

答案 1 :(得分:1)

您可以在zip使用递归:

from pprint import pprint
dict1 = {'Personnel':
     {'Performance': ''},
 'Gaming':
     {'Status': '',
      'Bug Status': ''},
 'Compatible':
     {'Minimum': '',
      'Integrity': '',
      'Scaling': ''},
 'Comparison':
     {'Difference':
          {'DirectX': ''},
      'Vendor':
          {'Intel': '',
           'Xiaomi': ''}
      }
 }

dict2 = {'Personnel':
         {'Performance': '10.5',
          'Maximum': '50.5'},
     'Gaming':
         {'Status': 'Cool',
          'Bug Status': 'None',
          'Green Status': 'Black',
          },
     'Compatible':
         {'Minimum': '5',
          'Integrity': 'Yes',
          'Scaling': 'No'},
     'Comparison':
         {'Difference':
              {'DirectX': '50',
               'Android': '70'},
          'Vendor':
              { 'Xiaomi': '40'}

          },
     'Another property':
         {
             'Testinfo': 'TestTest',
             'Important': {
                 'Wow': 'MuchDoge'
             }
         }
     }

def update(h, j):
   return {a:d if (a == c and not isinstance(b, dict)) or not isinstance(b, dict) or not isinstance(d, dict) else update(b.items(), d.items()) for (a, b), (c, d) in zip(h, j)}

pprint(update(dict1.items(), dict2.items()))

输出:

{'Comparison': {'Difference': 'TestTest', 'Vendor': {'Intel': 
'MuchDoge'}},
'Compatible': {'Integrity': 'Yes', 'Minimum': '5', 'Scaling': 'No'},
'Gaming': {'Bug Status': {'Xiaomi': '40'},
           'Status': {'Android': '70', 'DirectX': '50'}},
'Personnel': {'Performance': '10.5'}}