Converti due elenchi in un dizionario
-
03-07-2019 - |
Domanda
Immagina di avere:
keys = ['name', 'age', 'food']
values = ['Monty', 42, 'spam']
Qual è il modo più semplice per produrre il seguente dizionario?
a_dict = {'name' : 'Monty', 'age' : 42, 'food' : 'spam'}
Soluzione
In questo modo:
>>> keys = ['a', 'b', 'c']
>>> values = [1, 2, 3]
>>> dictionary = dict(zip(keys, values))
>>> print(dictionary)
{'a': 1, 'b': 2, 'c': 3}
Voila :-) Il costruttore a coppie dict
e la funzione zip
sono incredibilmente utili: https://docs.python.org/3/library/functions.html#func-dict
Altri suggerimenti
Prova questo:
>>> import itertools
>>> keys = ('name', 'age', 'food')
>>> values = ('Monty', 42, 'spam')
>>> adict = dict(itertools.izip(keys,values))
>>> adict
{'food': 'spam', 'age': 42, 'name': 'Monty'}
In Python 2, è anche più economico nel consumo di memoria rispetto a zip
.
Immagina di avere:
keys = ('name', 'age', 'food') values = ('Monty', 42, 'spam')
Qual è il modo più semplice per produrre il seguente dizionario?
dict = {'name' : 'Monty', 'age' : 42, 'food' : 'spam'}
Più performante - Python 2.7 e 3, comprensione dettata:
Un possibile miglioramento nell'uso del costruttore dict consiste nell'utilizzare la sintassi nativa di una comprensione dict (non una comprensione dell'elenco, come altri l'hanno erroneamente definita):
new_dict = {k: v for k, v in zip(keys, values)}
In Python 2, zip
restituisce un elenco, per evitare di creare un elenco non necessario, utilizzare invece izip
(con aliasing zip è possibile ridurre le modifiche al codice quando si passa a Python 3).
from itertools import izip as zip
Quindi è ancora:
from itertools import izip
new_dict = dict(izip(keys, values))
Python 2, ideale per < = 2.6
itertools
da dict
diventa <=> in Python 3. <=> è meglio di zip per Python 2 (perché evita la creazione di elenchi non necessari), e ideale per 2.6 o versioni precedenti:
new_dict = dict(zip(keys, values))
Python 3
In Python 3, <=> diventa la stessa funzione presente nel modulo <=>, quindi è semplicemente:
>>> new_dict
{'age': 42, 'name': 'Monty', 'food': 'spam'}
Una comprensione del dict sarebbe comunque più performante (vedere la revisione della performance alla fine di questa risposta).
Risultato per tutti i casi:
In tutti i casi:
>>> 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)
Spiegazione:
Se guardiamo la guida su <=> vediamo che ci sono varie forme di argomenti:
>>> zip(keys, values)
[('name', 'Monty'), ('age', 42), ('food', 'spam')]
L'approccio ottimale è utilizzare un iterabile evitando di creare strutture di dati non necessarie. In Python 2, zip crea un elenco non necessario:
>>> list(zip(keys, values))
[('name', 'Monty'), ('age', 42), ('food', 'spam')]
In Python 3, l'equivalente sarebbe:
>>> zip(keys, values)
<zip object at 0x7f0e2ad029c8>
e Python 3 <=> crea semplicemente un oggetto iterabile:
generator_expression = ((k, v) for k, v in zip(keys, values))
dict(generator_expression)
Poiché vogliamo evitare di creare strutture di dati non necessarie, di solito vogliamo evitare <=> di Python 2 (poiché crea un elenco non necessario).
Alternative meno performanti:
Questa è un'espressione del generatore passata al costruttore del dict:
dict((k, v) for k, v in zip(keys, values))
o equivalentemente:
dict([(k, v) for k, v in zip(keys, values)])
E questa è una comprensione dell'elenco che viene passata al costruttore del dict:
>>> 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
Nei primi due casi, uno strato aggiuntivo di calcolo non operativo (quindi non necessario) viene posizionato sopra lo zip iterabile e, nel caso della comprensione dell'elenco, viene creato inutilmente un elenco aggiuntivo. Mi aspetterei che fossero tutti meno performanti, e certamente non di più.
Revisione delle prestazioni:
In Python 3.4.3 a 64 bit, su Ubuntu 14.04, ordinato dal più veloce al più lento:
<*>>>> keys = ('name', 'age', 'food')
>>> values = ('Monty', 42, 'spam')
>>> dict(zip(keys, values))
{'food': 'spam', 'age': 42, 'name': 'Monty'}
Puoi anche usare la comprensione del dizionario in Python & # 8805; 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'}
Un modo più naturale è usare la comprensione del dizionario
keys = ('name', 'age', 'food')
values = ('Monty', 42, 'spam')
dict = {keys[i]: values[i] for i in range(len(keys))}
Se devi trasformare chiavi o valori prima di creare un dizionario, allora espressione del generatore potrebbe essere usato. Esempio:
>>> adict = dict((str(k), v) for k, v in zip(['a', 1, 'b'], [2, 'c', 3]))
Dai un'occhiata Codice come un Pythonista: Idiomatic Python .
con Python 3.x, vale per la comprensione del dict
keys = ('name', 'age', 'food')
values = ('Monty', 42, 'spam')
dic = {k:v for k,v in zip(keys, values)}
print(dic)
Altre informazioni su comprensioni qui , c'è un esempio:
>>> print {i : chr(65+i) for i in range(4)}
{0 : 'A', 1 : 'B', 2 : 'C', 3 : 'D'}
Per coloro che hanno bisogno di un codice semplice e non sono & # 8217; t familiarità con zip
:
List1 = ['This', 'is', 'a', 'list']
List2 = ['Put', 'this', 'into', 'dictionary']
Questo può essere fatto con una riga di codice:
d = {List1[n]: List2[n] for n in range(len(List1))}
- 2018/4/18
La soluzione migliore è ancora:
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'}
Traspone:
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')
puoi usare questo codice qui sotto:
dict(zip(['name', 'age', 'food'], ['Monty', 42, 'spam']))
Ma assicurati che la lunghezza degli elenchi sia la stessa. Se la lunghezza non è la stessa, allora la funzione zip trasforma quella più lunga.
Ecco anche un esempio di aggiunta di un valore di elenco nel tuo dizionario
list1 = ["Name", "Surname", "Age"]
list2 = [["Cyd", "JEDD", "JESS"], ["DEY", "AUDIJE", "PONGARON"], [21, 32, 47]]
dic = dict(zip(list1, list2))
print(dic)
assicurati sempre che la tua " Key " (list1) sia sempre nel primo parametro.
{'Name': ['Cyd', 'JEDD', 'JESS'], 'Surname': ['DEY', 'AUDIJE', 'PONGARON'], 'Age': [21, 32, 47]}
metodo senza funzione 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'}