Home > Software engineering >  Creating nested dictionary giving range of values for each key
Creating nested dictionary giving range of values for each key

Time:10-26

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
  • Related