Python 如何合并具有相同密钥或不同密钥的多个DICT?

Python 如何合并具有相同密钥或不同密钥的多个DICT?,python,python-3.x,dictionary,merge,Python,Python 3.x,Dictionary,Merge,我有多个dict/键值对,如下所示: d1 = {key1: x1, key2: y1} d2 = {key1: x2, key2: y2} 我希望结果是一个新的dict(以最有效的方式,如果可能的话): 实际上,我希望结果d是: d = {key1: (x1.x1attrib, x2.x2attrib), key2: (y1.y1attrib, y2.y2attrib)} 如果有人告诉我如何得到第一个结果,我可以找出其余的结果。这里有一个通用的解决方案,可以处理任意数量的字典,

我有多个dict/键值对,如下所示:

d1 = {key1: x1, key2: y1}  
d2 = {key1: x2, key2: y2}  
我希望结果是一个新的dict(以最有效的方式,如果可能的话):

实际上,我希望结果d是:

d = {key1: (x1.x1attrib, x2.x2attrib), key2: (y1.y1attrib, y2.y2attrib)}  

如果有人告诉我如何得到第一个结果,我可以找出其余的结果。

这里有一个通用的解决方案,可以处理任意数量的字典,当键只在某些字典中时:

from collections import defaultdict

d1 = {1: 2, 3: 4}
d2 = {1: 6, 3: 7}

dd = defaultdict(list)

for d in (d1, d2): # you can list as many input dicts as you want here
    for key, value in d.items():
        dd[key].append(value)

print(dd)
显示:

defaultdict(<type 'list'>, {1: [2, 6], 3: [4, 7]})
defaultdict(,{1:[2,6],3:[4,7]})

另外,要获取
.attrib
,只需将
附加(value)
更改为
附加(value.attrib)

假设所有关键字始终存在于所有dict中:

ds = [d1, d2]
d = {}
for k in d1.iterkeys():
    d[k] = tuple(d[k] for d in ds)
注意:在Python 3.x中,使用以下代码:

ds = [d1, d2]
d = {}
for k in d1.keys():
  d[k] = tuple(d[k] for d in ds)
如果dic包含numpy阵列:

ds = [d1, d2]
d = {}
for k in d1.keys():
  d[k] = np.concatenate(list(d[k] for d in ds))

这里有一种方法,即使两个听写器没有相同的键,也可以使用:

d1 = {'a':'test','b':'btest','d':'dreg'}
d2 = {'a':'cool','b':'main','c':'clear'}

d = {}

for key in set(d1.keys() + d2.keys()):
    try:
        d.setdefault(key,[]).append(d1[key])        
    except KeyError:
        pass

    try:
        d.setdefault(key,[]).append(d2[key])          
    except KeyError:
        pass

print d
这将产生以下输入:

{'a': ['test', 'cool'], 'c': ['clear'], 'b': ['btest', 'main'], 'd': ['dreg']}

如果你只有d1和d2

from collections import defaultdict

d = defaultdict(list)
for a, b in d1.items() + d2.items():
    d[a].append(b)
紧凑的可能性

d1={'a':1,'b':2}
d2={'c':3,'d':4}
context={**d1, **d2}
context
{'b': 2, 'c': 3, 'd': 4, 'a': 1}

Python 3.x更新

来自Eli Bendersky的回答:

Python 3删除了dict.iteritems,而使用dict.items。 请参见Python wiki:

确保钥匙的顺序相同:

dict2_sorted = {i:dict2[i] for i in dict1.keys()}

keys = dict1.keys()
values = zip(dict1.values(), dict2_sorted.values())
dictionary = dict(zip(keys, values))
给出:

{'m': (2, 1), 'n': (4, 3)}

为了补充这两个列表解决方案,这里有一个处理单个列表的解决方案

示例列表(与NetworkX相关;此处手动格式化以便于阅读):

请注意相同边的重复值(由元组定义)。要将这些“值”与其对应的“键”进行比较:

参考资料

  • [这条线]
  • [Python文档]
    • 来自blubb的回答:

      还可以使用每个列表中的值直接形成元组

      ds = [d1, d2]
      d = {}
      for k in d1.keys():
        d[k] = (d1[k], d2[k])
      
      如果对元组有特定的排序,这可能会很有用

      ds = [d1, d2, d3, d4]
      d = {}
      for k in d1.keys():
        d[k] = (d3[k], d1[k], d4[k], d2[k]) #if you wanted tuple in order of d3, d1, d4, d2
      

      即使两个字典中的键不同,此函数也会合并两个dict:

      def组合指令(d1、d2):
      返回{
      k:元组(d[k]表示d in(d1,d2),如果k in d)
      对于集合中的k(d1.keys())|集合(d2.keys())
      }
      
      例如:

      d1 = {
          'a': 1,
          'b': 2,
      }
      d2` = {
          'b': 'boat',
          'c': 'car',
      }
      combine_dict(d1, d2)
      # Returns: {
      #    'a': (1,),
      #    'b': (2, 'boat'),
      #    'c': ('car',)
      # }
      

      假设您拥有所有键的列表(您可以通过遍历所有字典并获取它们的键来获取此列表)。让我们把它命名为
      listKeys
      。此外:

      • listValues
        是所需单个键的所有值的列表 合并
      • allDicts
        :要合并的所有词典

      这个库帮助了我,我有一个同名但值不同的嵌套键的dict列表,每个其他解决方案都会覆盖这些嵌套键

      从deepmerge导入始终\u合并
      def过程参数(参数):
      临时列表=[]
      对于参数中的x:
      以开放(x,'r')作为流:
      临时列表追加(yaml.安全加载(流))
      始终返回合并。合并(*临时列表)
      
      如果键嵌套:

      d1 = { 'key1': { 'nkey1': 'x1' }, 'key2': { 'nkey2': 'y1' } } 
      d2 = { 'key1': { 'nkey1': 'x2' }, 'key2': { 'nkey2': 'y2' } }
      
      收益率:

      {'key1': {'nkey1': ('x1', 'x2')}, 'key2': {'nkey2': ('y1', 'y2')}}
      

      假设有两个字典具有完全相同的键,下面是最简洁的方法(两种解决方案都应该使用python3)

      
      d1={'a':1,'b':2,'c':3}
      d2={'a':5,'b':6,'c':7}
      #从其中一本字典中获取密钥
      ks=[k代表d1.keys()中的k]
      印刷品(ks)
      ['a','b','c']
      #在可用键上调用每个字典中的值
      d_merged={k:(d1[k],d2[k])表示k在ks}中
      打印(d_合并)
      {'a':(1,5),'b':(2,6),'c':(3,7)}
      #将值合并为列表的步骤
      d_merged={k:[d1[k],d2[k]]表示k在ks}
      打印(d_合并)
      {'a':[1,5],'b':[2,6],'c':[3,7]}
      

      如果有两个字典有一些常用键,但有几个不同的键,那么应该准备一个所有键的列表

      
      d1={'a':1,'b':2,'c':3,'d':9}
      d2={'a':5,'b':6,'c':7,'e':4}
      #从其中一本字典中获取密钥
      d1_ks=[k代表d1.keys()中的k]
      d2_ks=[k代表d2.keys()中的k]
      all_ks=设置(d1_ks+d2_ks)
      打印(全部)
      ['a','b','c','d','e']
      #在可用键上调用每个字典中的值
      d_merged={k:[d1.get(k),d2.get(k)]表示所有_-ks中的k}
      打印(d_合并)
      {'d':[9,无],'a':[1,5],'b':[2,6],'c':[3,7],'e':[None,4]}
      
      对于具有相同键的两个或多个DICT,更好的表示方法是使用数据框
      pandas
      IMO:

      d1 = {"key1": "x1", "key2": "y1"}  
      d2 = {"key1": "x2", "key2": "y2"}  
      d3 = {"key1": "x3", "key2": "y3"}  
      
      d1_df = pd.DataFrame.from_dict(d1, orient='index')
      d2_df = pd.DataFrame.from_dict(d2, orient='index')
      d3_df = pd.DataFrame.from_dict(d3, orient='index')
      
      fin_df = pd.concat([d1_df, d2_df, d3_df], axis=1).T.reset_index(drop=True)
      fin_df
      
          key1 key2
      0   x1   y1
      1   x2   y2
      2   x3   y3
      

      @萨利尔:我们可以假设每个键都存在于所有字典中吗?可能存在Hi Space_C0wb0y的重复,是的,所有字典中都存在键。指定所有DICT是否具有相同的键是绝对重要的。我认为OP希望值为
      元组
      而不是
      列表
      @A A:这真的重要吗?在多输入dict的更一般的情况下,元组的构建将更为棘手,因为有些键不在任何地方,因此您可能需要从
      defaultdict
      中生成一个正常的
      dict
      ,这样您就可以对不存在的键执行正常的
      dict
      行为,等等:
      dd=dict(dd)
      @Ned:good point,但这取决于最终使用的data@Eli:不,这没关系,但我只是想根据OP想要的东西来做,希望你能为元组找到一个解决方案:-)我想只要“在d1中为k”就行了。用d.get(k,None)代替d[k]@tahir这意味着dict具有不匹配的键,因此在
      d1
      上迭代是不正确的(它可能会错过其他dict中的键)。对于Python3用户:d1.iterkeys()=d1.items(),在Python3.x中对我仍然不起作用。即使我的值不是数组,我也尝试过这个方法,而且它是有效的。但是,输出的值将是数组。问题是如何用同一个键合并dict。您的答案不是必需的。
      values()
      中元素的顺序未定义,因此您可能正在合并来自无关键的值。我只是应用了更改,以便它现在可以捕获您的反馈。我认为更改不会解决问题。你需要使用
      sorted(d.items())
      sorted(d.keys())
      来获得可预测的结果。你能举个例子来证明这一点吗?dict2_sorted是python中的一个排序字典!我做了一个sm
      ec_num_collection_dict = {k:v for k, v in zip(ec_num_collection, ec_num_collection)}
      
      print('\nec_num_collection_dict:\n{}'.format(dict(ec_num_collection)))
        ec_num_collection_dict:
        {(82, 433): ['1.1.1.1', '1.1.1.2'],
        (22, 182): ['1.1.1.27'],
        (22, 3785): ['1.2.4.1'],
        (22, 36): ['6.4.1.1'],
        (145, 36): ['1.1.1.37'],
        (36, 154): ['2.3.3.1', '2.3.3.8'],
        (36, 72): ['4.1.1.32'],
        ...}
      
      ds = [d1, d2]
      d = {}
      for k in d1.keys():
        d[k] = (d1[k], d2[k])
      
      ds = [d1, d2, d3, d4]
      d = {}
      for k in d1.keys():
        d[k] = (d3[k], d1[k], d4[k], d2[k]) #if you wanted tuple in order of d3, d1, d4, d2
      
      d1 = {
          'a': 1,
          'b': 2,
      }
      d2` = {
          'b': 'boat',
          'c': 'car',
      }
      combine_dict(d1, d2)
      # Returns: {
      #    'a': (1,),
      #    'b': (2, 'boat'),
      #    'c': ('car',)
      # }
      
      result = {}
      for k in listKeys:
          listValues = [] #we will convert it to tuple later, if you want.
          for d in allDicts:
             try:
                  fileList.append(d[k]) #try to append more values to a single key
              except:
                  pass
          if listValues: #if it is not empty
              result[k] = typle(listValues) #convert to tuple, add to new dictionary with key k
      
      d1 = { 'key1': { 'nkey1': 'x1' }, 'key2': { 'nkey2': 'y1' } } 
      d2 = { 'key1': { 'nkey1': 'x2' }, 'key2': { 'nkey2': 'y2' } }
      
      ds = [d1, d2]
      d = {}
      for k in d1.keys():
          for k2 in d1[k].keys():
              d.setdefault(k, {})
              d[k].setdefault(k2, [])
              d[k][k2] = tuple(d[k][k2] for d in ds)
      
      {'key1': {'nkey1': ('x1', 'x2')}, 'key2': {'nkey2': ('y1', 'y2')}}
      
      d1 = {"key1": "x1", "key2": "y1"}  
      d2 = {"key1": "x2", "key2": "y2"}  
      d3 = {"key1": "x3", "key2": "y3"}  
      
      d1_df = pd.DataFrame.from_dict(d1, orient='index')
      d2_df = pd.DataFrame.from_dict(d2, orient='index')
      d3_df = pd.DataFrame.from_dict(d3, orient='index')
      
      fin_df = pd.concat([d1_df, d2_df, d3_df], axis=1).T.reset_index(drop=True)
      fin_df
      
          key1 key2
      0   x1   y1
      1   x2   y2
      2   x3   y3