Converter uma lista em um dicionário em Python


189

Digamos que eu tenha uma lista aem Python cujas entradas mapeiem convenientemente para um dicionário. Cada elemento par representa a chave do dicionário e o seguinte elemento ímpar é o valor

por exemplo,

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

e gostaria de convertê-lo em um dicionário b, onde

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

Qual é a maneira sintaticamente mais limpa de fazer isso?


Respostas:


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

Se afor grande, você provavelmente fará algo como o seguinte, que não cria listas temporárias como a acima.

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

No Python 3, você também pode usar uma compreensão de ditado, mas, ironicamente, acho que a maneira mais simples de fazê-lo será com range()e len(), que normalmente seria um cheiro de código.

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

Portanto, o iter()/izip()método ainda é provavelmente o mais Pythonic no Python 3, embora, como observa a EOL em um comentário, zip()já seja preguiçoso no Python 3, portanto você não precisa izip().

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

Se você quiser em uma linha, precisará trapacear e usar um ponto e vírgula. ;-)


9
… Ou simplesmente zip(i, i), no Python 3, já que zip()agora retorna um iterador.
Eric O Lebigot

5
Note que Python 2.7.3 também tem dict compreensão
user1438003

56

Resposta simples

Outra opção (cortesia de Alex Martelli - fonte ):

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

Nota relacionada

Se você tem isso:

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

e você deseja isso (cada elemento da lista digitando um determinado valor (2 neste caso)):

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

você pode usar:

>>> dict((k,2) for k in a)
{'double': 2, 'bi': 2, 'two': 2, 'duo': 2}

2
Isso é apenas para Python 3?
Tagar

2
use fromkeys. >>> dict.fromkeys(a, 2) {'bi': 2, 'double': 2, 'duo': 2, 'two': 2}
Gdogg

1
Isso está fazendo algo além do que a pergunta está fazendo.
#

17

Você pode usar uma compreensão de ditado para isso com bastante facilidade:

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

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

Isso é equivalente ao loop for abaixo:

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

10

Algo que eu acho muito legal, que é se a sua lista tiver apenas 2 itens:

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

Lembre-se, o dict aceita qualquer iterável que contenha uma iterável, onde cada item na iterável deve ser iterável com exatamente dois objetos.


rápido e simples, apenas para adicionar se a lista contiver mais de dois itens e use dict (ls) em vez de dict ([ls]). Para por exemplo se ls = [ 'a', 'b', 'c', 'd'], em seguida, de dicionários (ls)
ankit Tyagi

1
Agradável e elegante. 'cada item no iterável deve ser iterável com exatamente dois objetos.' é o fato chave aqui.
Abhijeet

4

Pode não ser o mais pitônico, mas

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

10
leia sobreenumerate
SilentGhost

5
enumerate não permite especificar um tamanho da etapa, mas você pode usar for i, key in enumerate(a[::2]):. Ainda unpythonic desde o construtor dict pode fazer a maioria do trabalho aqui para você
John La Rooy

@ SilentGhost, gnibbler: muito obrigado por ampliar meus horizontes! Certificarei de incorporá-lo o máximo possível no futuro!
Sahhhm

@gnibbler: Você poderia explicar um pouco mais sobre como a for i, key in enumerate(a[::2]):abordagem pode funcionar? Os valores do par resultantes seriam 0 helloe 1 1, e não está claro para mim como usá-los para produzir {'hello':'world', '1':'2'}.
27511 martineau

1
@martineau, você está correto. Eu acho que eu devo ter significadoenumerate(a)[::2]
John La Rooy

4

Você pode fazer isso muito rápido sem criar matrizes extras, portanto isso funcionará mesmo para matrizes muito grandes:

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

Se você possui um gerador a, melhor ainda:

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

Aqui está o resumo:

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

isso fará com que um dicionário com iguais pares de chave e valor ( {'hello':'hello','world':'world','1':'1','2':'2'})
mik

Não, tudo funciona muito bem. Por favor, leia com mais atenção. Ele diz: "Se você tem um gerador e ..." Se você não tem um gerador, use a primeira linha. O segundo é uma alternativa que seria útil se você tivesse um gerador em vez de uma lista, como faria na maioria das vezes.
Topkara 19/04/19

1

Você também pode fazer assim (string para listar a conversão aqui e depois para o dicionário)

    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


0

Não tenho certeza se isso é pitônico, mas 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))

0

tente o código abaixo:

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

0

Você também pode tentar essa abordagem, salvar as chaves e os valores na lista diferente e, em seguida, usar o 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)))

resultado:

{'test3': '3', 'test1': '1', 'test2': '2', 'test4': '4'}

0
{x: a[a.index(x)+1] for x in a if a.index(x) % 2 ==0}

result : {'hello': 'world', '1': '2'}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.