如何使用相同的键合并多个dicts?

时间:2011-05-10 06:50:04

标签: python dictionary merge

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

d1 = {key1: x1, key2: y1}  
d2 = {key1: x2, key2: y2}  

我希望结果是一个新的词典(如果可能的话,以最有效的方式):

d = {key1: (x1, x2), key2: (y1, y2)}  

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

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

如果有人告诉我如何获得第一个结果,我可以弄清楚其余部分。

16 个答案:

答案 0 :(得分:51)

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

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.iteritems():
        dd[key].append(value)

print(dd)

节目:

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

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

答案 1 :(得分:17)

假设所有密钥始终存在于所有dicts中:

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))

答案 2 :(得分:3)

如果你只有d1和d2,

from collections import defaultdict

d = defaultdict(list)
for a, b in d1.items() + d2.items():
    d[a].append(b)

答案 3 :(得分:2)

这是一种可以使用的方法,即使两个词典都没有相同的键也可以使用:

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']}

答案 4 :(得分:1)

dict1 = {'m': 2, 'n': 4}
dict2 = {'n': 3, 'm': 1}

确保按键顺序相同:

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)}

答案 5 :(得分:1)

假定您具有所有键的列表(可以通过遍历所有字典并获取其键来获得此列表)。我们将其命名为listKeys。另外:

  • listValues是您想要的单个键的所有值的列表 合并。
  • allDicts:您要合并的所有字典。
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

答案 6 :(得分:0)

def merge(d1, d2, merge):
    result = dict(d1)
    for k,v in d2.iteritems():
        if k in result:
            result[k] = merge(result[k], v)
        else:
            result[k] = v
    return result

d1 = {'a': 1, 'b': 2}
d2 = {'a': 1, 'b': 3, 'c': 2}
print merge(d1, d2, lambda x, y:(x,y))

{'a': (1, 1), 'c': 2, 'b': (2, 3)}

答案 7 :(得分:0)

Python 3.x更新

来自Eli Bendersky回答:

Python 3删除了dict.iteritems而不是使用dict.items。 请参阅Python wiki:https://wiki.python.org/moin/Python3.0

{{1}}

答案 8 :(得分:0)

作为对两列表解决方案的补充,这是用于处理单个列表的解决方案。

示例列表(与NetworkX相关;在此处手动设置格式以提高可读性)

ec_num_list = [((src, tgt), ec_num['ec_num']) for src, tgt, ec_num in G.edges(data=True)]

print('\nec_num_list:\n{}'.format(ec_num_list))
ec_num_list:
[((82, 433), '1.1.1.1'),
  ((82, 433), '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'),
  ((36, 154), '2.3.3.8'),
  ((36, 72), '4.1.1.32'),
  ...] 

请注意相同边(由元组定义)的重复值。要将这些“值”整理为对应的“键”:

from collections import defaultdict
ec_num_collection = defaultdict(list)
for k, v in ec_num_list:
    ec_num_collection[k].append(v)

print('\nec_num_collection:\n{}'.format(ec_num_collection.items()))
ec_num_collection:
[((82, 433), ['1.1.1.1', '1.1.1.2']),   ## << grouped "values"
((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']),    ## << grouped "values"
((36, 72), ['4.1.1.32']),
...] 

如果需要,将该列表转换为字典:

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'],
  ...}

参考

答案 9 :(得分:0)

来自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

答案 10 :(得分:0)

即使两个字典中的键不同,此方法也会合并两个字典:

def combine_dict(d1, d2):
    combined = {}
    for k in set(d1.keys()) | set(d2.keys()):
        combined[k] = tuple(d[k] for d in [d1, d2] if k in d)
    return combined

示例:

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

答案 11 :(得分:0)

这个库对我有帮助,我有一个具有相同名称但值不同的嵌套键的字典列表,所有其他解决方案都将覆盖这些嵌套键。

https://pypi.org/project/deepmerge/

from deepmerge import always_merger

def process_parms(args):
    temp_list = []
    for x in args:
        with open(x, 'r') as stream:
            temp_list.append(yaml.safe_load(stream))

    return always_merger.merge(*temp_list)

答案 12 :(得分:0)

如果键嵌套:

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')}}

答案 13 :(得分:0)

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


d1 = {'a': 1, 'b': 2, 'c':3}
d2 = {'a': 5, 'b': 6, 'c':7} 

# get keys from one of the dictionary
ks = [k for k in d1.keys()]

print(ks)
['a', 'b', 'c']

# call values from each dictionary on available keys
d_merged = {k: (d1[k], d2[k]) for k in ks}

print(d_merged)
{'a': (1, 5), 'b': (2, 6), 'c': (3, 7)}

# to merge values as list
d_merged = {k: [d1[k], d2[k]] for k in ks}
print(d_merged)
{'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} 

# get keys from one of the dictionary
d1_ks = [k for k in d1.keys()]
d2_ks = [k for k in d2.keys()]

all_ks = set(d1_ks + d2_ks)

print(all_ks)
['a', 'b', 'c', 'd', 'e']

# call values from each dictionary on available keys
d_merged = {k: [d1.get(k), d2.get(k)] for k in all_ks}

print(d_merged)
{'d': [9, None], 'a': [1, 5], 'b': [2, 6], 'c': [3, 7], 'e': [None, 4]}

答案 14 :(得分:0)

具有相同键的两个或多个字典的更好表示是 pandas Data Frame 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

答案 15 :(得分:-4)

紧凑的可能性

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