I am new to the python and dealing with dictionaries. I am getting 10 dictionaries like this
d1 = {'a': 13, 'b':4.53, 'c':3243, 'd':0.2323}
d2 = {'a': 12, 'b':4.3, 'c':373, 'd':0.263}
…
dn = {'a': 16, 'b':9.53, 'c':76843, 'd':13}
what I want to return nested dictionary which will contain min and max for each of the values. like this
d_out = {'a': {'min': 12,'max': 16},
'b': {'min': 4.3,'max': 9.53},
'c': {'min': 373,'max': 76843},
'd': {'min': 0.2323,'max': 13},
}
CodePudding user response:
One approach is to use collections.Counter
and take advantage of the fact that intersection computes the min, and union computes the max:
from collections import Counter
from operator import and_, or_
from functools import reduce
# toy data
dict1 = {'a': 13, 'b': 4.53, 'c': 3243, 'd': 0.2323}
dict2 = {'a': 12, 'b': 4.3, 'c': 373, 'd': 0.263}
dict3 = {'a': 16, 'b': 9.53, 'c': 76843, 'd': 13}
# conver to Counter
d = list(Counter(**di) for di in [dict1, dict2, dict3])
# find intersection i.e min
mi = reduce(and_, d)
# find union i.e max
ma = reduce(or_, d)
# build result dictionary
res = {key: {"min": value, "ma": ma[key]} for key, value in mi.items()}
print(res)
Output
{'a': {'min': 12, 'ma': 16}, 'b': {'min': 4.3, 'ma': 9.53}, 'c': {'min': 373, 'ma': 76843}, 'd': {'min': 0.2323, 'ma': 13}}
CodePudding user response:
Assuming the following input:
ds = [{'a': 13, 'b':4.53, 'c':3243, 'd':0.2323},
{'a': 12, 'b':4.3, 'c':373, 'd':0.263},
{'a': 16, 'b':9.53, 'c':76843, 'd':13},]
## or
# ds = [d1, d2, d3, ...]
You can use a dictionary comprehension with a bit of zip
/map
help:
dict(zip(ds[0],
map(lambda x: {'min': min(x), 'max': max(x)},
zip(*(d.values()
for d in ds)))))
output:
{'a': {'min': 12, 'max': 16},
'b': {'min': 4.3, 'max': 9.53},
'c': {'min': 373, 'max': 76843},
'd': {'min': 0.2323, 'max': 13}}
comparison of this approach and the nice Counter
trick from @Dani. Timing on 30k elements:
# dictionary comprehension
5.09 ms ± 202 µs per loop
# Counter trick
112 ms ± 2.65 ms per loop