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?

Mike
fonte
3
Possível duplicado de dicionário Marca da lista com python
Jeru Lucas

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. ;-)

kindall
fonte
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}
JobJob
fonte
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]
Chris Arena
fonte
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.

rix
fonte
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]
sahhhm
fonte
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
topkara
fonte
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
Stefan Gruenwald
fonte
1

Também estou muito interessado em ter uma linha para essa conversão, pois essa lista é o inicializador padrão para hash no Perl.

Uma resposta excepcionalmente abrangente é dada neste tópico -

O meu é um novato em Python), usando o Python 2.7 Generator Expressions , seria:

dict((a[i], a[i + 1]) for i in range(0, len(a) - 1, 2))

Oleksiy
fonte
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))
Manu
fonte
0

tente o código abaixo:

  >>> d2 = dict([('one',1), ('two', 2), ('three', 3)])
  >>> d2
      {'three': 3, 'two': 2, 'one': 1}
Muhammed
fonte
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'}
Aaditya Ura
fonte
0
{x: a[a.index(x)+1] for x in a if a.index(x) % 2 ==0}

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