Estoy creando un diccionario con claves y valores de listas:

keys = ['Ptot', 'P1', 'P2', 'P3', 'Q1', 'Q2', 'Q3']
val = ['max', 'first', 'first', 'first', 'first', 'first', 'first']

Puedo crear manualmente el diccionario de la siguiente manera:

dictionary = {'Ptot': 'max', 'P1': 'first', 'P2': 'first', 'P3': 'first', 'Q1': 'first', 'Q2': 'first', 'Q3': 'first'}

¿Cómo puedo crear de manera más elegante el dict de las listas mediante un bucle for? Mi problema es que el tamaño de las listas es mucho más grande que este ejemplo.

3
j36701 10 may. 2019 a las 15:52

3 respuestas

La mejor respuesta

Use un diccionario de comprensión, donde elija su clave y valor de la lista keys y val mientras itera sobre ellos, y solo para estar seguro si keys y {{X3} } tienen longitudes desiguales, puede comprimirlos todos juntos a través de itertools. zip_longest, que creará un iterador de la subsecuencia más larga, asegurándose de que si keys es más largo que val, no tenemos teclas para ellos, tal vez para reasignarlos en el futuro (Gracias @ quamrana)

from itertools import zip_longest
keys = ['Ptot', 'P1', 'P2', 'P3', 'Q1', 'Q2', 'Q3']
val = ['max', 'first', 'first', 'first', 'first', 'first', 'first']

print({k:v for k,v in zip_longest(keys, val)})

La salida es

{'Ptot': 'max', 'P1': 'first', 'P2': 'first', 'P3': 'first', 'Q1': 'first', 'Q2': 'first', 'Q3': 'first'}

Un ejemplo de mayor longitud de keys que val

from itertools import zip_longest
keys = ['Ptot', 'P1', 'P2', 'P3', 'Q1', 'Q2', 'Q3', 'QX', 'QY']
val = ['max', 'first', 'first', 'first', 'first', 'first', 'first']

print({k:v for k,v in zip_longest(keys, val)})

La salida será

{'Ptot': 'max', 'P1': 'first', 'P2': 'first', 
'P3': 'first', 'Q1': 'first', 'Q2': 'first', 'Q3': 'first', 
'QX': None, 'QY': None}

Así que vemos que las claves no se pierden aquí, sino que se usan y los valores se establecen en Ninguno, pero usando zip nos hará perder esas llaves.

Pero en caso de que solo queramos elegir elementos de la lista más pequeña, podemos hacer lo siguiente (gracias @MitchelPaulin)

from itertools import zip_longest
keys = ['Ptot', 'P1', 'P2', 'P3', 'Q1', 'Q2', 'Q3', 'QX', 'QY']
val = ['max', 'first', 'first', 'first', 'first', 'first', 'first']

#Pick the smaller of the 2 lengths and iterate only on those indexes
length = min(len(keys), len(val))
print({keys[idx]:val[idx] for idx in range(length)})
6
Devesh Kumar Singh 10 may. 2019 a las 13:01

Eche un vistazo a zip:

>>> d = dict(zip(keys, val))
>>> d
{'Ptot': 'max', 'P1': 'first', 'P2': 'first', 'P3': 'first', 'Q1': 'first', 'Q2': 'first', 'Q3': 'first'}

Haga un iterador que agregue elementos de cada uno de los iterables.

Devuelve un iterador de tuplas, donde la tupla i-ésima contiene el elemento i-ésimo de cada una de las secuencias de argumentos o iterables.

Luego pasamos el valor de retorno a dict para crear un diccionario. Esto es probablemente más eficiente que un simple ciclo, ya que las funciones integradas se ejecutan a velocidad C dentro de Python y los implementadores probablemente tuvieron más tiempo para optimizarlo.

11
Ayxan 10 may. 2019 a las 13:01

Este enfoque utiliza zip con una simple adición de la segunda lista para que coincida con los tamaños.

l1=['Ptot', 'P1', 'P2', 'P3', 'Q1', 'Q2', 'Q3', 'Q4' ]
l2=['max', 'first' ]

# make sure we have the same length
for i in range (len(l1)-len(l2)): l2.append(None)

d={}
d={k:v for k,v in zip(l1,l2)}
print(d)

Tenga en cuenta que usé append(None) como zip_longest utiliza fillvalue=None.


{'Ptot': 'max', 'P1': 'first', 'P2': None, 'P3': None, 'Q1': None, 'Q2': None, 'Q3': None, 'Q4': None}
0
prosti 10 may. 2019 a las 20:34