web-dev-qa-db-fra.com

Convertir deux listes en dictionnaire

Imaginez que vous avez:

keys = ['name', 'age', 'food']
values = ['Monty', 42, 'spam']

Quel est le moyen le plus simple de produire le dictionnaire suivant?

a_dict = {'name' : 'Monty', 'age' : 42, 'food' : 'spam'}
1023
Guido

Comme ça:

>>> keys = ['a', 'b', 'c']
>>> values = [1, 2, 3]
>>> dictionary = dict(Zip(keys, values))
>>> print(dictionary)
{'a': 1, 'b': 2, 'c': 3}

Le constructeur paire dict et la fonction Zip sont extrêmement utiles: https://docs.python.org/3/library/functions.html#func-dict

1834
Dan Lenski

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'}

Dans Python 2, la consommation de mémoire est également plus économique que Zip.

121
Mike Davis

Imaginez que vous avez:

keys = ('name', 'age', 'food')
values = ('Monty', 42, 'spam')

Quel est le moyen le plus simple de produire le dictionnaire suivant?

dict = {'name' : 'Monty', 'age' : 42, 'food' : 'spam'}

Le plus performant - Python 2.7 et 3, compréhension de dict:

Une amélioration possible de l'utilisation du constructeur dict consiste à utiliser la syntaxe native d'une compréhension dict (et non une compréhension liste, comme d'autres l'ont dit à tort):

new_dict = {k: v for k, v in Zip(keys, values)}

Dans Python 2, Zip renvoie une liste. Pour éviter de créer une liste inutile, utilisez izip à la place (un alias de Zip peut réduire les modifications de code lorsque vous passez à Python 3.) .

from itertools import izip as Zip

Donc c'est toujours:

new_dict = {k: v for k, v in Zip(keys, values)}

Python 2, idéal pour <= 2.6

izip de itertools devient Zip en Python 3. izip est meilleur que Zip pour Python 2 (car cela évite la création inutile de listes) , et idéal pour 2.6 ou inférieur:

from itertools import izip
new_dict = dict(izip(keys, values))

Python 3

Dans Python 3, Zip devient la même fonction que celle contenue dans le module itertools, de sorte qu'il s'agit simplement:

new_dict = dict(Zip(keys, values))

Une compréhension dictée serait cependant plus performante (voir l’analyse des performances à la fin de cette réponse).

Résultat pour tous les cas:

Dans tous les cas:

>>> new_dict
{'age': 42, 'name': 'Monty', 'food': 'spam'}

Explication:

Si nous regardons l'aide sur dict, nous voyons qu'elle prend diverses formes 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ératif tout en évitant de créer des structures de données inutiles. Dans Python 2, Zip crée une liste inutile:

>>> Zip(keys, values)
[('name', 'Monty'), ('age', 42), ('food', 'spam')]

Dans Python 3, l'équivalent serait:

>>> list(Zip(keys, values))
[('name', 'Monty'), ('age', 42), ('food', 'spam')]

et Python 3's 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 les Zip de Python 2 2 (car cela crée une liste inutile).

Alternatives moins performantes:

C'est une expression génératrice transmise au constructeur de 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ératoire (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.

Revue de la performance:

En 64 bits Python 3.4.3, sous Ubuntu 14.04, classés du plus rapide au plus lent:

>>> min(timeit.repeat(lambda: {k: v for k, v in Zip(keys, values)}))
0.7836067057214677
>>> min(timeit.repeat(lambda: dict(Zip(keys, values))))
1.0321204089559615
>>> min(timeit.repeat(lambda: {keys[i]: values[i] for i in range(len(keys))}))
1.0714934510178864
>>> min(timeit.repeat(lambda: dict([(k, v) for k, v in Zip(keys, values)])))
1.6110592018812895
>>> min(timeit.repeat(lambda: dict((k, v) for k, v in Zip(keys, values))))
1.7361853648908436
112
Aaron Hall
>>> keys = ('name', 'age', 'food')
>>> values = ('Monty', 42, 'spam')
>>> dict(Zip(keys, values))
{'food': 'spam', 'age': 42, 'name': 'Monty'}
30
iny

Vous pouvez également utiliser la compréhension du dictionnaire dans 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'}
27
Brendan Berg

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))}
14
Polla A. Fattah

Si vous devez transformer des clés ou des valeurs avant de créer un dictionnaire, vous pouvez utiliser un expression génératrice . Exemple:

>>> adict = dict((str(k), v) for k, v in Zip(['a', 1, 'b'], [2, 'c', 3])) 

Jetez un oeil Code comme un Pythonista: Python idiomatique .

12
jfs

avec Python 3.x, opte pour la compréhension de dict

keys = ('name', 'age', 'food')
values = ('Monty', 42, 'spam')

dic = {k:v for k,v in Zip(keys, values)}

print(dic)

Plus sur 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'}
10
kiriloff

Pour ceux qui ont besoin de code simple et ne sont pas familiers avec Zip:

List1 = ['This', 'is', 'a', 'list']
List2 = ['Put', 'this', 'into', 'dictionary']

Cela peut être fait par une ligne de code:

d = {List1[n]: List2[n] for n in range(len(List1))}
5
exploitprotocol
  • 2018-04-18

La meilleure solution est toujours:

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'}

Le transposer:

    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')
3
Algebra

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.Ensuite, la fonction Zip inverse le plus long.

1
Akash Nayak

J'avais ce doute alors que j'essayais de résoudre un problème lié aux graphes. Le problème que j’avais, c’était de définir une liste d’adjacence vide et je voulais initialiser tous les nœuds avec une liste vide; c’est à ce moment-là que j’ai pensé que je vérifiais si c’était assez rapide, mais si cela valait la peine de faire une opération Zip. plutôt que la simple affectation paire clé-valeur. Après tout, le facteur temps est un facteur important pour briser la glace. J'ai donc effectué une 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 En abrégé: 3.535717916001886

Itération: 5.051560923002398 En abrégé: 6.255070794999483

Itération: 6.52859034499852 En abrégé: 8.221581164998497

Itération: 8.683652416999394 En abrégé: 12.599181543999293

Itération: 11.587241565001023 En abrégé: 15.27298851100204

Itération: 14.816342867001367 En abrégé: 17.162912737003353

Itération: 16.645022411001264 En abrégé: 19.976680120998935

Vous pouvez clairement voir qu'après un certain point, l'approche itérative à la nième étape dépasse le temps pris par la méthode de la sténographie à la n-1ième étape.

1
Mayank Prakash

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 "Key" (list1) est toujours dans le premier paramètre.

{'Name': ['Cyd', 'JEDD', 'JESS'], 'Surname': ['DEY', 'AUDIJE', 'PONGARON'], 'Age': [21, 32, 47]}
1
Jayceed Saymon Deyro
keys = ['name', 'age', 'food']
values = ['Monty', 42, 'spam']
new_dict = dict(Zip(keys,values))
print(new_dict)
1
Shishir Nanoty

Vous pouvez le faire avec une ligne en utilisant la compréhension du dictionnaire:

a_dict={key:value for key,value in Zip(keys,values)}

et c'est tout. Profiter de Python .....;)

1
Maz1978

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'}
0
xiyurui