Respostas:
Como isso:
>>> keys = ['a', 'b', 'c']
>>> values = [1, 2, 3]
>>> dictionary = dict(zip(keys, values))
>>> print(dictionary)
{'a': 1, 'b': 2, 'c': 3}
Voila :-) O dict
construtor e a zip
função em pares são extremamente úteis: https://docs.python.org/3/library/functions.html#func-dict
{thing}
é açúcar sintático para construir set()
um elemento contendo um. {*iterable}
é açúcar sintático para construir um set
contendo vários elementos. {k:v}
ou {**mapping}
vai construir um dict
, mas isso é sintaticamente bastante distintos.
{}
para dicionários. De fato, se tentarmos, type({})
a saída é dict
. Mas, de fato, se tentarmos type({thing})
, o resultado é set
.
{k:v for k, v in zip(keys, values)}
. Acontece que podemos. +1.
Imagine que você tem:
keys = ('name', 'age', 'food') values = ('Monty', 42, 'spam')
Qual é a maneira mais simples de produzir o seguinte dicionário?
dict = {'name' : 'Monty', 'age' : 42, 'food' : 'spam'}
dict
construtor comzip
new_dict = dict(zip(keys, values))
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 para dict
e zip
, mas não forma estruturas de dados intermediárias desnecessárias ou precisa lidar com pesquisas locais no aplicativo de funções.
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):
new_dict = {k: v for k, v in zip(keys, values)}
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-o izip
(o alias do zip pode reduzir as alterações de código quando você passa para o Python 3).
from itertools import izip as zip
Então isso ainda é (2.7):
new_dict = {k: v for k, v in zip(keys, values)}
izip
from itertools
torna - se zip
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:
from itertools import izip
new_dict = dict(izip(keys, values))
Em todos os casos:
>>> new_dict
{'age': 42, 'name': 'Monty', 'food': 'spam'}
Se olharmos para a ajuda dict
, vemos que são necessárias várias formas de argumentos:
>>> help(dict)
class dict(object)
| dict() -> new empty dictionary
| dict(mapping) -> new dictionary initialized from a mapping object's
| (key, value) pairs
| dict(iterable) -> new dictionary initialized as if via:
| d = {}
| for k, v in iterable:
| d[k] = v
| dict(**kwargs) -> new dictionary initialized with the name=value pairs
| in the keyword argument list. For example: dict(one=1, two=2)
A abordagem ideal é usar um iterável, evitando criar estruturas de dados desnecessárias. No Python 2, o zip cria uma lista desnecessária:
>>> zip(keys, values)
[('name', 'Monty'), ('age', 42), ('food', 'spam')]
No Python 3, o equivalente seria:
>>> list(zip(keys, values))
[('name', 'Monty'), ('age', 42), ('food', 'spam')]
e o Python 3 zip
apenas cria um objeto iterável:
>>> zip(keys, values)
<zip object at 0x7f0e2ad029c8>
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).
Esta é uma expressão geradora que está sendo passada para o construtor dict:
generator_expression = ((k, v) for k, v in zip(keys, values))
dict(generator_expression)
ou equivalente:
dict((k, v) for k, v in zip(keys, values))
E esta é uma compreensão de lista sendo transmitida ao construtor de dict:
dict([(k, v) for k, v in zip(keys, values)])
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.
No Python 3.8.2 de 64 bits fornecido pelo Nix, no Ubuntu 16.04, ordenado do mais rápido para o mais lento:
>>> min(timeit.repeat(lambda: dict(zip(keys, values))))
0.6695233230129816
>>> min(timeit.repeat(lambda: {k: v for k, v in zip(keys, values)}))
0.6941362579818815
>>> min(timeit.repeat(lambda: {keys[i]: values[i] for i in range(len(keys))}))
0.8782548159942962
>>>
>>> min(timeit.repeat(lambda: dict([(k, v) for k, v in zip(keys, values)])))
1.077607496001292
>>> min(timeit.repeat(lambda: dict((k, v) for k, v in zip(keys, values))))
1.1840861019445583
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:
min
parece ser uma maneira ruim de comparar o desempenho. Certamentemean
e / oumax
seriam indicadores muito mais úteis para uso real.
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íamos max
apenas o resultado mais extremo - o mais provável de ser afetado por esse evento.
Um comentarista também diz:
No python 3.6.8, usando valores médios, a compreensão do ditado é realmente ainda mais rápida, em cerca de 30% para essas pequenas listas. Para listas maiores (números aleatórios de 10k), a
dict
chamada é cerca de 10% mais rápida.
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ê usar mean
ou max
eu consideraria seus resultados sem sentido.
Vamos usar um tamanho mais realista em nossos principais exemplos:
import numpy
import timeit
l1 = list(numpy.random.random(100))
l2 = list(numpy.random.random(100))
E vemos aqui que dict(zip(...
, de fato, corre mais rápido em conjuntos de dados maiores em cerca de 20%.
>>> min(timeit.repeat(lambda: {k: v for k, v in zip(l1, l2)}))
9.698965263989521
>>> min(timeit.repeat(lambda: dict(zip(l1, l2))))
7.9965161079890095
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. Certamente mean
e / ou max
seriam indicadores muito mais úteis para uso real.
dict
chamada é cerca de 10% mais rápida.
Tente o seguinte:
>>> import itertools
>>> keys = ('name', 'age', 'food')
>>> values = ('Monty', 42, 'spam')
>>> adict = dict(itertools.izip(keys,values))
>>> adict
{'food': 'spam', 'age': 42, 'name': 'Monty'}
No Python 2, também é mais econômico em consumo de memória em comparação com zip
.
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
usado zip
para substituir itertools.izip
no Python 2 pythonhosted.org/six .
Você também pode usar as compreensões de dicionário no Python ≥ 2.7:
>>> keys = ('name', 'age', 'food')
>>> values = ('Monty', 42, 'spam')
>>> {k: v for k, v in zip(keys, values)}
{'food': 'spam', 'age': 42, 'name': 'Monty'}
Uma maneira mais natural é usar a compreensão do dicionário
keys = ('name', 'age', 'food')
values = ('Monty', 42, 'spam')
dict = {keys[i]: values[i] for i in range(len(keys))}
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:
>>> adict = dict((str(k), v) for k, v in zip(['a', 1, 'b'], [2, 'c', 3]))
Dê uma olhada no Code Like a Pythonista: Idiomatic Python .
com o Python 3.x, vale a pena compreender o dict
keys = ('name', 'age', 'food')
values = ('Monty', 42, 'spam')
dic = {k:v for k,v in zip(keys, values)}
print(dic)
Mais sobre a compreensão de dict aqui , um exemplo está lá:
>>> print {i : chr(65+i) for i in range(4)}
{0 : 'A', 1 : 'B', 2 : 'C', 3 : 'D'}
Para aqueles que precisam de código simples e não estão familiarizados com zip
:
List1 = ['This', 'is', 'a', 'list']
List2 = ['Put', 'this', 'into', 'dictionary']
Isso pode ser feito por uma linha de código:
d = {List1[n]: List2[n] for n in range(len(List1))}
List1
for maior queList2
for n in range(len(List1))
é um antipadrão
A melhor solução ainda é:
In [92]: keys = ('name', 'age', 'food')
...: values = ('Monty', 42, 'spam')
...:
In [93]: dt = dict(zip(keys, values))
In [94]: dt
Out[94]: {'age': 42, 'food': 'spam', 'name': 'Monty'}
Transponha:
lst = [('name', 'Monty'), ('age', 42), ('food', 'spam')]
keys, values = zip(*lst)
In [101]: keys
Out[101]: ('name', 'age', 'food')
In [102]: values
Out[102]: ('Monty', 42, 'spam')
você pode usar este código abaixo:
dict(zip(['name', 'age', 'food'], ['Monty', 42, 'spam']))
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.
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.
import timeit
def dictionary_creation(n_nodes):
dummy_dict = dict()
for node in range(n_nodes):
dummy_dict[node] = []
return dummy_dict
def dictionary_creation_1(n_nodes):
keys = list(range(n_nodes))
values = [[] for i in range(n_nodes)]
graph = dict(zip(keys, values))
return graph
def wrapper(func, *args, **kwargs):
def wrapped():
return func(*args, **kwargs)
return wrapped
iteration = wrapper(dictionary_creation, n_nodes)
shorthand = wrapper(dictionary_creation_1, n_nodes)
for trail in range(1, 8):
print(f'Itertion: {timeit.timeit(iteration, number=trails)}\nShorthand: {timeit.timeit(shorthand, number=trails)}')
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.
Aqui também está um exemplo de adição de um valor de lista no seu dicionário
list1 = ["Name", "Surname", "Age"]
list2 = [["Cyd", "JEDD", "JESS"], ["DEY", "AUDIJE", "PONGARON"], [21, 32, 47]]
dic = dict(zip(list1, list2))
print(dic)
sempre verifique se a sua "Chave" (lista1) está sempre no primeiro parâmetro.
{'Name': ['Cyd', 'JEDD', 'JESS'], 'Surname': ['DEY', 'AUDIJE', 'PONGARON'], 'Age': [21, 32, 47]}
Você também pode tentar com uma lista que é uma combinação de duas listas;)
a = [1,2,3,4]
n = [5,6,7,8]
x = []
for i in a,n:
x.append(i)
print(dict(zip(x[0], x[1])))
método sem função zip
l1 = [1,2,3,4,5]
l2 = ['a','b','c','d','e']
d1 = {}
for l1_ in l1:
for l2_ in l2:
d1[l1_] = l2_
l2.remove(l2_)
break
print (d1)
{1: 'd', 2: 'b', 3: 'e', 4: 'a', 5: 'c'}
dictionary = {zip(keys, values)}
não vai funcionar. Você deve declarar explicitamente como #dict(...)