python - Cómo crear una lista de diccionarios a partir de un diccionario con listas de diferentes longitudes
dictionary list-comprehension (5)
Aquí hay otro enfoque:
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)
Salida :
[{''height'': 164, ''age'': 13, ''job'': ''programmer'', ''name'': ''bob''}, {''height'': 188, ''age'': 19, ''name'': ''john''}, {''age'': 23, ''name'': ''harry''}, {''name'': ''mary''}]
Quiero crear una lista de diccionarios con el mismo elemento de índice de cada lista.
Tengo este diccionario:
d = {''name'': [''bob'', ''john'', ''harry'', ''mary''], ''age'': [13, 19, 23], ''height'': [164, 188], ''job'': [''programmer'']}
La salida deseada es:
d2 = [{''name'': ''bob'', ''age'': 13, ''height'': 164, ''job'': ''programmer''}, {''name'': ''john'', ''age'': 19, ''height'': 188}, {''name'': ''harry'', ''age'': 23}, {''name'': ''mary''}]
He intentado algo como esto:
d2 = [dict(zip(d, t)) for t in zip(*d.values())]
Pero mi salida es:
d2 = [{''name'': ''bob'', ''age'': 13, ''height'': 164, ''job'': ''programmer''}]
Creo que esto está sucediendo porque las listas tienen diferentes longitudes.
Puede usar
itertools.zip_longest
y filtrar los valores
None
:
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''}]
Puedes usar
zip_longest
aquí:
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())
]
Si los valores también pueden ser
None
, podemos evitarlo usando un valor ficticio:
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)
]
Aquí el ficticio es un objeto que estamos seguros de que no forma parte de los elementos en
d
(ya que lo construimos después de que construimos
d
).
Al usar una comparación
is
, podemos saber si ese valor fue el "valor de relleno".
Thi nos dará:
>>> d2
[{''name'': ''bob'', ''age'': 13, ''height'': 164, ''job'': ''programmer''}, {''name'': ''john'', ''age'': 19, ''height'': 188}, {''name'': ''harry'', ''age'': 23}, {''name'': ''mary''}]
Simplemente guarde todo y agregue esta declaración de importación:
desde itertools import zip_longest como zip
Una solución simple sin usar zip_longest, para el registro:
d = {''name'': [''bob'', ''john'', ''harry'', ''mary''], ''age'': [13, 19, 23], ''height'': [164, 188], ''job'': [''programmer'']}
recordset = [{k: v[i] for k, v in d.items() if i < len(v)} for i in range(max([len(l) for l in d.values()]))]
print(recordset) # >> [{''name'': ''bob'', ''age'': 13, ''height'': 164, ''job'': ''programmer''},
{''name'': ''john'', ''age'': 19, ''height'': 188},
{''name'': ''harry'', ''age'': 23},
{''name'': ''mary''}]