How to create a list of dictionaries from a dictionary with lists of different lengths
You can use itertools.zip_longest
and filter out None
values:
from itertools import zip_longest
[{x: y for x, y in zip(d, t) if y is not None} for t in zip_longest(*d.values())]
# [{'name': 'bob', 'age': 13, 'height': 164, 'job': 'programmer'},
# {'name': 'john', 'age': 19, 'height': 188},
# {'name': 'harry', 'age': 23},
# {'name': 'mary'}]
You can use zip_longest
here:
from itertools import zip_longest
keys = d.keys()
d2 = [
{k: v for k, v in zip(keys, vs) if v is not None}
for vs in zip_longest(*d.values())
]
If the values can be None
as well, we can circumvent that by using a dummy value:
from itertools import zip_longest
keys = d.keys()
dummy = object()
d2 = [
{k: v for k, v in zip(keys, vs) if v is not dummy}
for vs in zip_longest(*d.values(), fillvalue=dummy)
]
Here the dummy is an object which we are sure that is not part of the items in d
(since we construct it after we constructed d
). By using an is
comparison, we thus can know if that value was the "fillvalue".
This will give us:
>>> d2
[{'name': 'bob', 'age': 13, 'height': 164, 'job': 'programmer'}, {'name': 'john', 'age': 19, 'height': 188}, {'name': 'harry', 'age': 23}, {'name': 'mary'}]
Here is another approach :
d = {'name': ['bob', 'john', 'harry', 'mary'], 'age': [13, 19, 23], 'height': [164, 188], 'job': ['programmer']}
m = max(map(len, d.values()))
d1 = {k : (v if len(v)==m else v+['']*(m-len(v))) for k,v in d.items()}
d2 = [{k:v for k,v in zip(d, t) if v} for t in zip(*d1.values())]
print(d2)
Output :
[{'height': 164, 'age': 13, 'job': 'programmer', 'name': 'bob'}, {'height': 188, 'age': 19, 'name': 'john'}, {'age': 23, 'name': 'harry'}, {'name': 'mary'}]