python dictionary list-comprehension itertools

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''}]