I have four nested dictionaries:
a = {
1: {'a': 123, 'b': 222, 'c': 888},
2: {'a': 333, 'b': 555, 'c': 345}}
b = {
1: {'d': 456, 'e': 333, 'f': 333},
2: {'d': 555, 'e': 233, 'f': 433}}
c = {
1: {'g': 789, 'h': 444, 'i': 999},
2: {'g': 456, 'h': 333, 'i': 333}}
d = {
1: {'j': 111, 'k': 555, 'l': 222},
2: {'j': 456, 'k': 333, 'l': 333, 'm': 555}}
I want to concatenate/merge them into a new dictionary and group by the main key. The desired output is:
result = {
1: {'a': 123, 'b': 222, 'c': 888, 'd': 456, 'e': 333, 'f': 333, 'g': 789, 'h': 444, 'i': 999, 'j': 111, 'k': 555, 'l': 222},
2: {'a': 333, 'b': 555, 'c': 345, 'd': 555, 'e': 233, 'f': 433, 'g': 456, 'h': 333, 'i': 333, 'j': 456, 'k': 333, 'l': 333, 'm': 555}}
Each dictionary (a,b,c,d) has exactly 200 main keys (1 to 200) - I've only shown 2 entries each. There are no duplicate sub keys, but there are sometimes more subkeys in one than another (see "d").
I realize there are numerous very similar questions on stackoverflow, but the ones I found seem to involve something else (tuples, lists, combining only two dictionaries, etc.) and I have not been able to adapt any to my situation. An unsuccessful attempt (based on a similar question) that seemed logical given what I want the result to be:
result = {key: a[key] b[key] c[key] d[key] for key in a}
CodePudding user response:
You can use reduce()
with defaultdict()
to build up the result. For each key in the (outer) dictionary, we accumulate the key-value pairs corresponding to the inner dictionary (i.e. dictionary that a key maps to) using reduce()
:
from functools import reduce
from collections import defaultdict
dictionaries = [a, b, c, d]
# Can use dict.__or__ in Python 3.9 , rather than dict(**x[k], **y[k])
result = reduce(
lambda x, y: {k: dict(**x[k], **y[k]) for k in y},
dictionaries, defaultdict(dict)
)
print(result)
This outputs:
{
1: {'a': 123, 'b': 222, 'c': 888, 'd': 456, 'e': 333, 'f': 333, 'g': 789, 'h': 444, 'i': 999, 'j': 111, 'k': 555, 'l': 222},
2: {'a': 333, 'b': 555, 'c': 345, 'd': 555, 'e': 233, 'f': 433, 'g': 456, 'h': 333, 'i': 333, 'j': 456, 'k': 333, 'l': 333, 'm': 555}
}
CodePudding user response:
Use the |
operator to combine all the sub-dictionaries together:
import functools
result = {
main_key: functools.reduce(
dict.__or__,
(sub_dicts[main_key] for sub_dicts in (a, b, c, d))
)
for main_key in a
}
CodePudding user response:
This is also an alternative way to solve your problem
dd = {}
for k in a:
dd[k] = {**a[k], **b[k], **c[k], **d[k]}
Output:
{1: {'a': 123,
'b': 222,
'c': 888,
'd': 456,
'e': 333,
'f': 333,
'g': 789,
'h': 444,
'i': 999,
'j': 111,
'k': 555,
'l': 222},
2: {'a': 333,
'b': 555,
'c': 345,
'd': 555,
'e': 233,
'f': 433,
'g': 456,
'h': 333,
'i': 333,
'j': 456,
'k': 333,
'l': 333,
'm': 555}}
CodePudding user response:
You can use **
merging multi dict
and create one dict
from them:
>>> {k: {**v, **b.get(k,{}), **c.get(k,{}), **d.get(k, {})} for k,v in a.items()}
{1: {'a': 123,
'b': 222,
'c': 888,
'd': 456,
'e': 333,
'f': 333,
'g': 789,
'h': 444,
'i': 999,
'j': 111,
'k': 555,
'l': 222},
2: {'a': 333,
'b': 555,
'c': 345,
'd': 555,
'e': 233,
'f': 433,
'g': 456,
'h': 333,
'i': 333,
'j': 456,
'k': 333,
'l': 333,
'm': 555}}
CodePudding user response:
You can try using ** to merge multiple dicts together.
a = {
1: {'a': 123, 'b': 222, 'c': 888},
2: {'a': 333, 'b': 555, 'c': 345}}
b = {
1: {'d': 456, 'e': 333, 'f': 333},
2: {'d': 555, 'e': 233, 'f': 433}}
c = {
1: {'g': 789, 'h': 444, 'i': 999},
2: {'g': 456, 'h': 333, 'i': 333}}
d = {
1: {'j': 111, 'k': 555, 'l': 222},
2: {'j': 456, 'k': 333, 'l': 333, 'm': 555}}
result = {}
for i in range(1,len(a) 1):
l = {**a[i], **b[i], **c[i], **d[i]}
result[i] = l
print(result)
"""
{1: {'a': 123, 'b': 222, 'c': 888, 'd': 456, 'e': 333, 'f': 333, 'g': 789, 'h': 444, 'i': 999, 'j': 111, 'k': 555, 'l': 222},
2: {'a': 333, 'b': 555, 'c': 345, 'd': 555, 'e': 233, 'f': 433, 'g': 456, 'h': 333, 'i': 333, 'j': 456, 'k': 333, 'l': 333, 'm': 555}}
"""
CodePudding user response:
you can use simply the or operation on dictionary
a =
{1: {'a': 123, 'b': 222, 'c': 888},
2: {'a': 333, 'b': 555, 'c': 345}}
b =
{1: {'d': 456, 'e': 333, 'f': 333},
2: {'d': 555, 'e': 233, 'f': 433}}
c =
{1: {'g': 789, 'h': 444, 'i': 999},
2: {'g': 456, 'h': 333, 'i': 333}}
d =
{1: {'j': 111, 'k': 555, 'l': 222},
2: {'j': 456, 'k': 333, 'l': 333, 'm': 555}}
result =
{1: a[1] | b[1] | c[1] | d[1],
2: a[2] | b[2] | c[2] | d[2]}
print(result)
output :
{1:
{'a': 123, 'b': 222, 'c': 888, 'd': 456, 'e': 333, 'f': 333, 'g': 789, 'h': 444, 'i': 999, 'j': 111, 'k': 555, 'l': 222},2:
{'a': 333, 'b': 555, 'c': 345, 'd': 555, 'e': 233, 'f': 433, 'g': 456, 'h':333, 'i': 333, 'j': 456, 'k': 333, 'l': 333, 'm': 555}
}