Convertir una lista a un diccionario en Python

191

Digamos que tengo una lista aen Python cuyas entradas se asignan convenientemente a un diccionario. Cada elemento par representa la clave del diccionario, y el siguiente elemento impar es el valor

por ejemplo,

a = ['hello','world','1','2']

y me gustaría convertirlo a un diccionario b, donde

b['hello'] = 'world'
b['1'] = '2'

¿Cuál es la forma sintácticamente más limpia de lograr esto?

Miguel
fuente
3
Posible duplicado de Make dictionary from list with python
Jeru Luke

Respuestas:

272
b = dict(zip(a[::2], a[1::2]))

Si aes grande, probablemente querrá hacer algo como lo siguiente, que no hace ninguna lista temporal como la anterior.

from itertools import izip
i = iter(a)
b = dict(izip(i, i))

En Python 3 también podría usar una comprensión de dict, pero irónicamente creo que la forma más sencilla de hacerlo será con range()y len(), que normalmente sería un olor a código.

b = {a[i]: a[i+1] for i in range(0, len(a), 2)}

Entonces, el iter()/izip()método sigue siendo probablemente el más Pythonic en Python 3, aunque como EOL señala en un comentario, zip()ya es flojo en Python 3, por lo que no es necesario izip().

i = iter(a)
b = dict(zip(i, i))

Si lo quieres en una línea, tendrás que hacer trampa y usar un punto y coma. ;-)

un poco
fuente
9
... o simplemente zip(i, i), en Python 3, ya que zip()ahora devuelve un iterador.
Eric O Lebigot
55
Tenga en cuenta que Python 2.7.3 también tiene comprensión dict
user1438003
56

Respuesta simple

Otra opción (cortesía de Alex Martelli - fuente ):

dict(x[i:i+2] for i in range(0, len(x), 2))

Nota relacionada

Si tienes esto:

a = ['bi','double','duo','two']

y quieres esto (cada elemento de la lista teclea un valor dado (2 en este caso)):

{'bi':2,'double':2,'duo':2,'two':2}

puedes usar:

>>> dict((k,2) for k in a)
{'double': 2, 'bi': 2, 'two': 2, 'duo': 2}
JobJob
fuente
2
¿Esto es solo para Python 3?
Tagar
2
uso fromkeys. >>> dict.fromkeys(a, 2) {'bi': 2, 'double': 2, 'duo': 2, 'two': 2}
Gdogg
1
Esto está haciendo algo más que lo que está haciendo la pregunta.
ozn
17

Puede usar una comprensión dict para esto con bastante facilidad:

a = ['hello','world','1','2']

my_dict = {item : a[index+1] for index, item in enumerate(a) if index % 2 == 0}

Esto es equivalente al ciclo for a continuación:

my_dict = {}
for index, item in enumerate(a):
    if index % 2 == 0:
        my_dict[item] = a[index+1]
Chris Arena
fuente
10

Algo que encuentro bastante bueno, que es que si tu lista tiene solo 2 elementos:

ls = ['a', 'b']
dict([ls])
>>> {'a':'b'}

Recuerde, dict acepta cualquier iterable que contenga un iterable donde cada elemento en el iterable debe ser un iterable con exactamente dos objetos.

rix
fuente
uno rápido y simple, solo para agregar si la lista contiene más de dos elementos, luego use dict (ls) en lugar de dict ([ls]). por ejemplo, si ls = ['a', 'b', 'c', 'd'] entonces dict (ls)
ankit tyagi
1
Agradable y elegante. 'cada elemento en el iterable debe ser un iterable con exactamente dos objetos'. Es el hecho clave aquí.
Abhijeet
4

Puede que no sea el más pitónico, pero

>>> b = {}
>>> for i in range(0, len(a), 2):
        b[a[i]] = a[i+1]
sahhhm
fuente
10
leer sobreenumerate
SilentGhost
55
enumerar no le permite especificar un tamaño de paso, pero podría usarlo for i, key in enumerate(a[::2]):. Todavía no es pitónico ya que el constructor dict puede hacer la mayor parte del trabajo aquí por usted
John La Rooy
@SilentGhost, gnibbler: ¡muchas gracias por ampliar mis horizontes! ¡Me aseguraré de incorporarlo tanto como sea posible en el futuro!
sahhhm
@gnibbler: ¿Podría explicar un poco más sobre cómo for i, key in enumerate(a[::2]):podría funcionar el enfoque? Los valores de pares resultantes serían 0 helloy 1 1, y no está claro para mí cómo usarlos para producir {'hello':'world', '1':'2'}.
Martineau
1
@martineau, tienes razón. Creo que debí haber querido decirenumerate(a)[::2]
John La Rooy
4

Puede hacerlo bastante rápido sin crear matrices adicionales, por lo que esto funcionará incluso para matrices muy grandes:

dict(izip(*([iter(a)]*2)))

Si tienes un generador a, aún mejor:

dict(izip(*([a]*2)))

Aquí está el resumen:

iter(h)    #create an iterator from the array, no copies here
[]*2       #creates an array with two copies of the same iterator, the trick
izip(*())  #consumes the two iterators creating a tuple
dict()     #puts the tuples into key,value of the dictionary
topkara
fuente
esto hará un diccionario con pares iguales de clave y valor ( {'hello':'hello','world':'world','1':'1','2':'2'})
mik
No, todo funciona bien. Por favor lea más cuidadosamente. Dice: "Si tiene un generador a ..." Si no tiene un generador, simplemente use la primera línea. La segunda es una alternativa que sería útil si tiene un generador en lugar de una lista, como lo haría la mayoría de las veces.
topkara
1

También puede hacerlo así (cadena para listar conversión aquí, luego conversión a un diccionario)

    string_list = """
    Hello World
    Goodbye Night
    Great Day
    Final Sunset
    """.split()

    string_list = dict(zip(string_list[::2],string_list[1::2]))

    print string_list
Stefan Gruenwald
fuente
0

No estoy seguro de si esto es pitónico, pero parece funcionar

def alternate_list(a):
   return a[::2], a[1::2]

key_list,value_list = alternate_list(a)
b = dict(zip(key_list,value_list))
Manu
fuente
0

intente debajo del código:

  >>> d2 = dict([('one',1), ('two', 2), ('three', 3)])
  >>> d2
      {'three': 3, 'two': 2, 'one': 1}
Muhammed
fuente
0

También puede probar este enfoque, guardar las claves y los valores en una lista diferente y luego usar el método dict

data=['test1', '1', 'test2', '2', 'test3', '3', 'test4', '4']

keys=[]
values=[]
for i,j in enumerate(data):
    if i%2==0:
        keys.append(j)
    else:
        values.append(j)

print(dict(zip(keys,values)))

salida:

{'test3': '3', 'test1': '1', 'test2': '2', 'test4': '4'}
Aaditya Ura
fuente
0
{x: a[a.index(x)+1] for x in a if a.index(x) % 2 ==0}

result : {'hello': 'world', '1': '2'}
Mahdi Ghelichi
fuente