Réponses:
Comme ça:
>>> keys = ['a', 'b', 'c']
>>> values = [1, 2, 3]
>>> dictionary = dict(zip(keys, values))
>>> print(dictionary)
{'a': 1, 'b': 2, 'c': 3}
Voila :-) Le dict
constructeur et la zip
fonction par paire sont extrêmement utiles: https://docs.python.org/3/library/functions.html#func-dict
{thing}
est du sucre syntaxique pour construire un set()
contenant un élément. {*iterable}
est du sucre syntaxique pour construire un set
contenant plusieurs éléments. {k:v}
ou {**mapping}
va construire un dict
, mais c'est syntaxiquement assez distinct.
{}
pour les dictionnaires. En fait, si nous essayons, type({})
la sortie est dict
. Mais en effet, si nous essayons, type({thing})
la sortie est set
.
{k:v for k, v in zip(keys, values)}
. Il s'avère que nous le pouvons. +1.
Imaginez que vous ayez:
keys = ('name', 'age', 'food') values = ('Monty', 42, 'spam')
Quelle est la manière la plus simple de produire le dictionnaire suivant?
dict = {'name' : 'Monty', 'age' : 42, 'food' : 'spam'}
dict
Constructeur le plus performant aveczip
new_dict = dict(zip(keys, values))
En Python 3, zip renvoie maintenant un itérateur paresseux, et c'est maintenant l'approche la plus performante.
dict(zip(keys, values))
ne nécessite la recherche globale unique pour dict
et zip
, mais il ne forme pas de structures de données intermédiaires inutiles ou n'a pas à traiter les recherches locales dans l'application de fonction.
Un finaliste proche de l'utilisation du constructeur de dict est d'utiliser la syntaxe native d'une compréhension de dict (pas une compréhension de liste , comme d'autres l'ont dit à tort):
new_dict = {k: v for k, v in zip(keys, values)}
Choisissez cette option lorsque vous devez mapper ou filtrer en fonction des clés ou de la valeur.
En Python 2, zip
renvoie une liste, pour éviter de créer une liste inutile, utilisez izip
plutôt (l'alias de zip peut réduire les modifications de code lorsque vous passez à Python 3).
from itertools import izip as zip
Donc ça reste (2.7):
new_dict = {k: v for k, v in zip(keys, values)}
izip
from itertools
devient zip
en Python 3. izip
est meilleur que zip pour Python 2 (car il évite la création de liste inutile), et idéal pour 2.6 ou inférieur:
from itertools import izip
new_dict = dict(izip(keys, values))
Dans tous les cas:
>>> new_dict
{'age': 42, 'name': 'Monty', 'food': 'spam'}
Si nous regardons l'aide, dict
nous voyons qu'elle prend une variété d'arguments:
>>> 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)
L'approche optimale consiste à utiliser un itérable tout en évitant de créer des structures de données inutiles. En Python 2, zip crée une liste inutile:
>>> zip(keys, values)
[('name', 'Monty'), ('age', 42), ('food', 'spam')]
En Python 3, l'équivalent serait:
>>> list(zip(keys, values))
[('name', 'Monty'), ('age', 42), ('food', 'spam')]
et Python 3 zip
crée simplement un objet itérable:
>>> zip(keys, values)
<zip object at 0x7f0e2ad029c8>
Puisque nous voulons éviter de créer des structures de données inutiles, nous voulons généralement éviter celles de Python 2 zip
(car cela crée une liste inutile).
Il s'agit d'une expression de générateur transmise au constructeur dict:
generator_expression = ((k, v) for k, v in zip(keys, values))
dict(generator_expression)
ou équivalent:
dict((k, v) for k, v in zip(keys, values))
Et ceci est une compréhension de liste transmise au constructeur de dict:
dict([(k, v) for k, v in zip(keys, values)])
Dans les deux premiers cas, une couche supplémentaire de calcul non opérationnel (donc inutile) est placée sur le zip itérable, et dans le cas de la compréhension de liste, une liste supplémentaire est créée inutilement. Je m'attendrais à ce qu'ils soient tous moins performants, et certainement pas plus.
En Python 3.8.2 64 bits fourni par Nix, sur Ubuntu 16.04, ordonné du plus rapide au plus lent:
>>> 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))
gagne même avec de petits ensembles de clés et de valeurs, mais pour des ensembles plus grands, les différences de performances deviendront plus importantes.
Un intervenant a déclaré:
min
semble être une mauvaise façon de comparer les performances. Sûrementmean
et / oumax
seraient des indicateurs beaucoup plus utiles pour une utilisation réelle.
Nous utilisons min
parce que ces algorithmes sont déterministes. Nous voulons connaître les performances des algorithmes dans les meilleures conditions possibles.
Si le système d'exploitation se bloque pour une raison quelconque, cela n'a rien à voir avec ce que nous essayons de comparer, nous devons donc exclure ce type de résultats de notre analyse.
Si nous l'utilisions mean
, ce genre d'événements fausserait considérablement nos résultats, et si nous l'utilisions, max
nous n'obtiendrions que le résultat le plus extrême - celui le plus probablement affecté par un tel événement.
Un commentateur dit également:
En python 3.6.8, en utilisant des valeurs moyennes, la compréhension du dict est en effet encore plus rapide, d'environ 30% pour ces petites listes. Pour les listes plus grandes (10 000 nombres aléatoires), l'
dict
appel est environ 10% plus rapide.
Je suppose que nous voulons dire dict(zip(...
avec 10 000 nombres aléatoires. Cela ressemble à un cas d'utilisation assez inhabituel. Il est logique que les appels les plus directs dominent dans les grands ensembles de données, et je ne serais pas surpris que les blocages du système d'exploitation dominent étant donné le temps qu'il faudrait pour exécuter ce test, faussant davantage vos chiffres. Et si vous utilisez mean
oumax
je considérerais vos résultats comme dénués de sens.
Utilisons une taille plus réaliste sur nos meilleurs exemples:
import numpy
import timeit
l1 = list(numpy.random.random(100))
l2 = list(numpy.random.random(100))
Et nous voyons ici que dict(zip(...
cela fonctionne en effet plus rapidement pour les grands ensembles de données d'environ 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 microsec pour {k: v for k, v in zip(headList, textList)}
. Je suggère le premier pour la lisibilité et la vitesse. Évidemment, cela arrive à l'argument min () vs mean () pour timeit.
min
semble être une mauvaise façon de comparer les performances. Sûrement mean
et / ou max
seraient des indicateurs beaucoup plus utiles pour une utilisation réelle.
dict
appel est environ 10% plus rapide.
Essaye ça:
>>> import itertools
>>> keys = ('name', 'age', 'food')
>>> values = ('Monty', 42, 'spam')
>>> adict = dict(itertools.izip(keys,values))
>>> adict
{'food': 'spam', 'age': 42, 'name': 'Monty'}
En Python 2, il est également plus économique en termes de consommation de mémoire par rapport à zip
.
zip
est déjà économique en consommation de mémoire. docs.python.org/3/library/functions.html#zip En fait, vous pouvez voir que six
utilise zip
dans Python 3 pour remplacer itertools.izip
dans Python 2 pythonhosted.org/six .
Vous pouvez également utiliser des compréhensions de dictionnaire en 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'}
Une façon plus naturelle consiste à utiliser la compréhension du dictionnaire
keys = ('name', 'age', 'food')
values = ('Monty', 42, 'spam')
dict = {keys[i]: values[i] for i in range(len(keys))}
dict
objet, pourquoi est-ce ainsi?, merci mec.
Si vous devez transformer des clés ou des valeurs avant de créer un dictionnaire, une expression de générateur peut être utilisée. Exemple:
>>> adict = dict((str(k), v) for k, v in zip(['a', 1, 'b'], [2, 'c', 3]))
Jetez un oeil Code Like a Pythonista: Idiomatic Python .
avec Python 3.x, opte pour les compréhensions dict
keys = ('name', 'age', 'food')
values = ('Monty', 42, 'spam')
dic = {k:v for k,v in zip(keys, values)}
print(dic)
Plus d'informations sur les compréhensions dict ici , un exemple est là:
>>> print {i : chr(65+i) for i in range(4)}
{0 : 'A', 1 : 'B', 2 : 'C', 3 : 'D'}
Pour ceux qui ont besoin de code simple et ne connaissent pas zip
:
List1 = ['This', 'is', 'a', 'list']
List2 = ['Put', 'this', 'into', 'dictionary']
Cela peut être fait par une seule ligne de code:
d = {List1[n]: List2[n] for n in range(len(List1))}
List1
est plus long queList2
for n in range(len(List1))
c'est un anti-pattern
La meilleure solution reste:
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'}
Transposez-le:
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')
vous pouvez utiliser ce code ci-dessous:
dict(zip(['name', 'age', 'food'], ['Monty', 42, 'spam']))
Mais assurez-vous que la longueur des listes sera la même.Si la longueur n'est pas la même, la fonction zip tourne la plus longue.
J'ai eu ce doute alors que j'essayais de résoudre un problème lié au graphique. Le problème que j'avais était que je devais définir une liste de contiguïté vide et que je voulais initialiser tous les nœuds avec une liste vide, c'est à ce moment-là que j'ai pensé que je vérifierais si elle est assez rapide, je veux dire si cela vaudrait la peine de faire une opération zip plutôt qu'une simple paire clé-valeur d'affectation. Après tout, la plupart du temps, le facteur temps est un brise-glace important. J'ai donc effectué l'opération timeit pour les deux approches.
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)}')
Pour n_nodes = 10 000 000 je reçois,
Itération: 2,825081646999024 Sténographie: 3,535717916001886
Itération: 5.051560923002398 Sténographie: 6.255070794999483
Itération: 6.52859034499852 Sténographie: 8.221581164998497
Itération: 8.683652416999394 Sténographie: 12.599181543999293
Itération: 11.587241565001023 Sténographie: 15.27298851100204
Itération: 14.816342867001367 Sténographie: 17.162912737003353
Itération: 16.645022411001264 Sténographie: 19.976680120998935
Vous pouvez voir clairement après un certain point, l'approche d'itération à la n_ième étape dépasse le temps pris par l'approche abrégée à la n-1_ième étape.
Voici également un exemple d'ajout d'une valeur de liste dans votre dictionnaire
list1 = ["Name", "Surname", "Age"]
list2 = [["Cyd", "JEDD", "JESS"], ["DEY", "AUDIJE", "PONGARON"], [21, 32, 47]]
dic = dict(zip(list1, list2))
print(dic)
assurez-vous toujours que votre "Clé" (list1) est toujours dans le premier paramètre.
{'Name': ['Cyd', 'JEDD', 'JESS'], 'Surname': ['DEY', 'AUDIJE', 'PONGARON'], 'Age': [21, 32, 47]}
Vous pouvez également essayer avec une liste qui est une combinaison de deux listes;)
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éthode sans fonction 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)}
cela ne fonctionnera pas. Vous devez déclarer explicitement quedict(...)