How to Merge a List of Dicts into a Single Dict

How do I merge a list of dicts into a single dict?

This works for dictionaries of any length:

>>> result = {}
>>> for d in L:
... result.update(d)
...
>>> result
{'a':1,'c':1,'b':2,'d':2}

As a comprehension:

# Python >= 2.7
{k: v for d in L for k, v in d.items()}

# Python < 2.7
dict(pair for d in L for pair in d.items())

How to merge dictionaries of dictionaries?

This is actually quite tricky - particularly if you want a useful error message when things are inconsistent, while correctly accepting duplicate but consistent entries (something no other answer here does..)

Assuming you don't have huge numbers of entries, a recursive function is easiest:

def merge(a, b, path=None):
"merges b into a"
if path is None: path = []
for key in b:
if key in a:
if isinstance(a[key], dict) and isinstance(b[key], dict):
merge(a[key], b[key], path + [str(key)])
elif a[key] == b[key]:
pass # same leaf value
else:
raise Exception('Conflict at %s' % '.'.join(path + [str(key)]))
else:
a[key] = b[key]
return a

# works
print(merge({1:{"a":"A"},2:{"b":"B"}}, {2:{"c":"C"},3:{"d":"D"}}))
# has conflict
merge({1:{"a":"A"},2:{"b":"B"}}, {1:{"a":"A"},2:{"b":"C"}})

note that this mutates a - the contents of b are added to a (which is also returned). If you want to keep a you could call it like merge(dict(a), b).

agf pointed out (below) that you may have more than two dicts, in which case you can use:

reduce(merge, [dict1, dict2, dict3...])

where everything will be added to dict1.

Note: I edited my initial answer to mutate the first argument; that makes the "reduce" easier to explain

PS: In python 3, you will also need from functools import reduce

How to merge dicts, collecting values from matching keys?

assuming all keys are always present in all dicts:

ds = [d1, d2]
d = {}
for k in d1.iterkeys():
d[k] = tuple(d[k] for d in ds)

Note: In Python 3.x use below code:

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

and if the dic contain numpy arrays:

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

How to create a list of dicts into a single dict with python?

mydict = { k:v for elt in mylist for k, v in elt.items()}

Merge dictionaries in a list of dictionaries by combining the values

You can iterate over lst and create a dictionary out where the keys correspond to "id" values in the dicts in lst and the values are dicts. In each iteration, check if the value under "language" key is a list or not and append to the list if it's a list, create a list, if not. Finally, pass the values of out to a list constructor for the final outcome.

out = {}
for d in lst:
if d['id'] in out:
if isinstance(out[d['id']]['language'], list):
out[d['id']]['language'].append(d['language'])
else:
out[d['id']]['language'] = [out[d['id']]['language'], d['language']]
else:
out[d['id']] = d
out = list(out.values())

Output:

[{'id': 1, 'name': 'Adel', 'language': ['С#', 'Python']},
{'id': 5, 'name': 'Dora', 'language': ['С#', 'Java']},
{'id': 6, 'name': 'Dars', 'language': 'Python'}]

How to combine a list of dictionaries to one dictionary

If you don't mind duplicate keys replacing earlier keys you can use:

from functools import reduce  # Python 3 compatibility 
d = reduce(lambda a, b: dict(a, **b), d)

This merges the first two dictionaries then merges each following dictionary into the result built so far.

Demo:

>>> d =[{'a': 4}, {'b': 20}, {'c': 5}, {'d': 3}]
>>> reduce(lambda a, b: dict(a, **b), d)
{'a': 4, 'c': 5, 'b': 20, 'd': 3}

Or if you need this to work for arbitrary (non string) keys (and you are using Python 3.5 or greater):

>>> d =[{4: 4}, {20: 20}, {5: 5}, {3: 3}]
>>> reduce(lambda a, b: dict(a, **b), d) # This wont work
TypeError: keywords must be strings
>>> reduce(lambda a, b: {**a, **b}, d) # Use this instead
{4: 4, 20: 20, 5: 5, 3: 3}

The first solution hacks the behaviour of keyword arguments to the dict function. The second solution is using the more general ** operator introduced in Python 3.5.

Merging a list of dicts into one dict with items appended to a list

You should use a set for creating the list of keys, if you don't care about their order. You could create it using a comprehension.

For the second part, you can use a dict comprehension, and create each list with a list comprehension:

def merge_dicts(list_of_dicts: list, missval=None):
'''Merges a list of dicts, having common keys into a single dict
with items appended to a list

>>> d1 = {'a' : 1, 'b': 2, 'c': 3}
>>> d2 = {'a':4, 'b':5 }
>>> d3 = {'d': 5}
>>> merge_dicts([d1, d2, d3], 'NA')
{'a': [1, 4, 'NA'], 'b': [2, 5, 'NA'],
'c': [3, 'NA', 'NA'], 'd': ['NA', 'NA', 5]}
'''
all_keys = {key for d in list_of_dicts for key in d.keys()}
merged = {k: [d.get(k, missval) for d in list_of_dicts] for k in all_keys}

return(merged)

d1 = {'a' : 1, 'b': 2, 'c': 3}
d2 = {'a':4, 'b':5 }
d3 = {'d': 5}
merge_dicts([d1, d2, d3], 'NA')

#{'a': [1, 4, 'NA'],
# 'b': [2, 5, 'NA'],
# 'c': [3, 'NA', 'NA'],
# 'd': ['NA', 'NA', 5]}


Related Topics



Leave a reply



Submit