Imagine que você tem:
keys = ['name', 'age', 'food']
values = ['Monty', 42, 'spam']
Qual é a maneira mais simples de produzir o seguinte dicionário?
a_dict = {'name' : 'Monty', 'age' : 42, 'food' : 'spam'}
python
list
dictionary
Guido
fonte
fonte
dictionary = {zip(keys, values)}
não vai funcionar. Você deve declarar explicitamente como #dict(...)
{thing}
é açúcar sintático para construirset()
um elemento contendo um.{*iterable}
é açúcar sintático para construir umset
contendo vários elementos.{k:v}
ou{**mapping}
vai construir umdict
, mas isso é sintaticamente bastante distintos.{}
para dicionários. De fato, se tentarmos,type({})
a saída édict
. Mas, de fato, se tentarmostype({thing})
, o resultado éset
.{k:v for k, v in zip(keys, values)}
. Acontece que podemos. +1.Melhor desempenho,
dict
construtor comzip
No Python 3, o zip agora retorna um iterador lento e agora é a abordagem de melhor desempenho.
dict(zip(keys, values))
requer a pesquisa global única paradict
ezip
, mas não forma estruturas de dados intermediárias desnecessárias ou precisa lidar com pesquisas locais no aplicativo de funções.Segundo classificado, compreensão do ditado:
Um corredor próximo ao uso do construtor dict é usar a sintaxe nativa de uma compreensão de dict (não uma compreensão de lista , como outros colocaram por engano):
Escolha isso quando precisar mapear ou filtrar com base nas chaves ou no valor.
No Python 2,
zip
retorna uma lista, para evitar a criação de uma lista desnecessária, use-oizip
(o alias do zip pode reduzir as alterações de código quando você passa para o Python 3).Então isso ainda é (2.7):
Python 2, ideal para <= 2.6
izip
fromitertools
torna - sezip
no Python 3.izip
é melhor que o zip para o Python 2 (porque evita a criação desnecessária de listas) e é ideal para o 2.6 ou abaixo:Resultado para todos os casos:
Em todos os casos:
Explicação:
Se olharmos para a ajuda
dict
, vemos que são necessárias várias formas de argumentos:A abordagem ideal é usar um iterável, evitando criar estruturas de dados desnecessárias. No Python 2, o zip cria uma lista desnecessária:
No Python 3, o equivalente seria:
e o Python 3
zip
apenas cria um objeto iterável:Como queremos evitar a criação de estruturas de dados desnecessárias, geralmente queremos evitar o Python 2
zip
(pois ele cria uma lista desnecessária).Alternativas com menos desempenho:
Esta é uma expressão geradora que está sendo passada para o construtor dict:
ou equivalente:
E esta é uma compreensão de lista sendo transmitida ao construtor de dict:
Nos dois primeiros casos, uma camada extra de computação não-operacional (portanto desnecessária) é colocada sobre o zip iterável e, no caso da compreensão da lista, uma lista extra é desnecessariamente criada. Eu esperaria que todos eles tivessem menos desempenho e certamente não mais.
Revisão de desempenho:
No Python 3.8.2 de 64 bits fornecido pelo Nix, no Ubuntu 16.04, ordenado do mais rápido para o mais lento:
dict(zip(keys, values))
vence mesmo com pequenos conjuntos de chaves e valores, mas para conjuntos maiores, as diferenças de desempenho se tornam maiores.Um comentarista disse:
Usamos
min
porque esses algoritmos são determinísticos. Queremos conhecer o desempenho dos algoritmos nas melhores condições possíveis.Se o sistema operacional travar por algum motivo, não tem nada a ver com o que estamos tentando comparar, portanto, precisamos excluir esses tipos de resultados de nossa análise.
Se usássemos
mean
, esses tipos de eventos distorceriam muito nossos resultados e, se os usássemos, obteríamosmax
apenas o resultado mais extremo - o mais provável de ser afetado por esse evento.Um comentarista também diz:
Presumo que queremos dizer
dict(zip(...
com 10k números aleatórios. Isso soa como um caso de uso bastante incomum. Faz sentido que as chamadas mais diretas dominem em grandes conjuntos de dados, e eu não ficaria surpreso se as falhas no sistema operacional estiverem dominando, dado o tempo que levaria para executar esse teste, distorcendo ainda mais seus números. E se você usarmean
oumax
eu consideraria seus resultados sem sentido.Vamos usar um tamanho mais realista em nossos principais exemplos:
E vemos aqui que
dict(zip(...
, de fato, corre mais rápido em conjuntos de dados maiores em cerca de 20%.fonte
dict(zip(headList, textList))
& 1,95 \ pm 0,030 microsseg para{k: v for k, v in zip(headList, textList)}
. Eu sugeriria o primeiro por legibilidade e velocidade. Obviamente, isso ocorre no argumento min () vs mean () para timeit.min
parece ser uma maneira ruim de comparar o desempenho. Certamentemean
e / oumax
seriam indicadores muito mais úteis para uso real.dict
chamada é cerca de 10% mais rápida.Tente o seguinte:
No Python 2, também é mais econômico em consumo de memória em comparação com
zip
.fonte
zip
já é econômico no consumo de memória. docs.python.org/3/library/functions.html#zip De fato, você pode ver que o Python 3 ésix
usadozip
para substituiritertools.izip
no Python 2 pythonhosted.org/six .fonte
Você também pode usar as compreensões de dicionário no Python ≥ 2.7:
fonte
Uma maneira mais natural é usar a compreensão do dicionário
fonte
dict
objeto, por que é assim ?, obrigado cara.Se você precisar transformar chaves ou valores antes de criar um dicionário, uma expressão geradora poderá ser usada. Exemplo:
Dê uma olhada no Code Like a Pythonista: Idiomatic Python .
fonte
com o Python 3.x, vale a pena compreender o dict
Mais sobre a compreensão de dict aqui , um exemplo está lá:
fonte
Para aqueles que precisam de código simples e não estão familiarizados com
zip
:Isso pode ser feito por uma linha de código:
fonte
List1
for maior queList2
for n in range(len(List1))
é um antipadrãoA melhor solução ainda é:
Transponha:
fonte
você pode usar este código abaixo:
Mas certifique-se de que o comprimento das listas seja o mesmo. Se o comprimento não for o mesmo. A função zip será a mais longa.
fonte
Eu tive essa dúvida enquanto tentava resolver um problema relacionado a gráficos. O problema que tive foi que eu precisava definir uma lista de adjacência vazia e queria inicializar todos os nós com uma lista vazia. Foi quando pensei em verificar se é rápida o suficiente, quero dizer se valerá a pena fazer uma operação zip em vez de um simples par de valores-chave de atribuição. Afinal, na maioria das vezes, o fator tempo é um importante quebra-gelo. Então, realizei a operação timeit para as duas abordagens.
Para n_nodes = 10.000.000, recebo,
Iteração: 2.825081646999024 Taquigrafia: 3.535717916001886
Iteração: 5.051560923002398 Taquigrafia: 6.255070794999483
Iteração: 6.52859034499852 Taquigrafia: 8.221581164998497
Iteração: 8.683652416999394 abreviação: 12.599181543999293
Iteração: 11.587241565001023 Taquigrafia: 15.27298851100204
Iteração: 14.816342867001367 Taquigrafia: 17.162912737003353
Iteração: 16.645022411001264 Taquigrafia: 19.976680120998935
Você pode ver claramente, depois de um certo ponto, que a abordagem de iteração na n-ésima etapa ultrapassa o tempo gasto pela abordagem abreviada na n-ésima etapa.
fonte
Aqui também está um exemplo de adição de um valor de lista no seu dicionário
sempre verifique se a sua "Chave" (lista1) está sempre no primeiro parâmetro.
fonte
Solução como compreensão de dicionário com enumerar:
Solução como loop com enumerar:
fonte
Você também pode tentar com uma lista que é uma combinação de duas listas;)
fonte
método sem função zip
fonte