Antworten:
So was:
>>> keys = ['a', 'b', 'c']
>>> values = [1, 2, 3]
>>> dictionary = dict(zip(keys, values))
>>> print(dictionary)
{'a': 1, 'b': 2, 'c': 3}
Voila :-) Der paarweise dict
Konstruktor und die zip
Funktion sind äußerst nützlich: https://docs.python.org/3/library/functions.html#func-dict
{thing}
ist syntaktischer Zucker, um ein set()
Element zu konstruieren, das ein Element enthält. {*iterable}
ist syntaktischer Zucker, um ein set
Element zu konstruieren, das mehrere Elemente enthält. {k:v}
oder {**mapping}
wird ein konstruieren dict
, aber das ist syntaktisch ziemlich verschieden.
{}
für Wörterbücher verwende. In der Tat, wenn wir versuchen, ist type({})
die Ausgabe dict
. Aber in der Tat, wenn wir es versuchen, type({thing})
dann ist die Ausgabe set
.
{k:v for k, v in zip(keys, values)}
. Es stellt sich heraus, dass wir es können. +1.
Stellen Sie sich vor, Sie haben:
keys = ('name', 'age', 'food') values = ('Monty', 42, 'spam')
Was ist der einfachste Weg, um das folgende Wörterbuch zu erstellen?
dict = {'name' : 'Monty', 'age' : 42, 'food' : 'spam'}
dict
Konstruktor mitzip
new_dict = dict(zip(keys, values))
In Python 3 gibt zip jetzt einen faulen Iterator zurück, und dies ist jetzt der performanteste Ansatz.
dict(zip(keys, values))
erfordert jeweils die einmalige globale Suche für dict
und zip
, bildet jedoch keine unnötigen Zwischendatenstrukturen oder muss sich mit lokalen Suchvorgängen in der Funktionsanwendung befassen.
Ein enger Zweitplatzierter bei der Verwendung des Diktatkonstruktors ist die Verwendung der nativen Syntax eines Diktatverständnisses (kein Listenverständnis , wie andere es fälschlicherweise ausgedrückt haben):
new_dict = {k: v for k, v in zip(keys, values)}
Wählen Sie diese Option, wenn Sie basierend auf den Schlüsseln oder dem Wert zuordnen oder filtern müssen.
Gibt in Python 2 zip
eine Liste zurück, um zu vermeiden, dass eine unnötige Liste erstellt wird. Verwenden Sie izip
stattdessen (Alias auf Zip kann Codeänderungen reduzieren, wenn Sie zu Python 3 wechseln).
from itertools import izip as zip
Das ist also immer noch (2.7):
new_dict = {k: v for k, v in zip(keys, values)}
izip
from itertools
wird zip
in Python 3. izip
ist besser als zip für Python 2 (da es die unnötige Listenerstellung vermeidet) und ideal für 2.6 oder niedriger:
from itertools import izip
new_dict = dict(izip(keys, values))
Auf alle Fälle:
>>> new_dict
{'age': 42, 'name': 'Monty', 'food': 'spam'}
Wenn wir uns die Hilfe dict
ansehen, sehen wir, dass es verschiedene Formen von Argumenten gibt:
>>> 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)
Der optimale Ansatz besteht darin, eine Iterable zu verwenden und gleichzeitig unnötige Datenstrukturen zu vermeiden. In Python 2 erstellt zip eine unnötige Liste:
>>> zip(keys, values)
[('name', 'Monty'), ('age', 42), ('food', 'spam')]
In Python 3 wäre das Äquivalent:
>>> list(zip(keys, values))
[('name', 'Monty'), ('age', 42), ('food', 'spam')]
und Python 3 zip
erstellt lediglich ein iterierbares Objekt:
>>> zip(keys, values)
<zip object at 0x7f0e2ad029c8>
Da wir vermeiden möchten, unnötige Datenstrukturen zu erstellen, möchten wir normalerweise Python 2 vermeiden zip
(da dadurch eine unnötige Liste erstellt wird).
Dies ist ein Generatorausdruck, der an den Diktatkonstruktor übergeben wird:
generator_expression = ((k, v) for k, v in zip(keys, values))
dict(generator_expression)
oder äquivalent:
dict((k, v) for k, v in zip(keys, values))
Und dies ist ein Listenverständnis, das an den Diktatkonstruktor weitergegeben wird:
dict([(k, v) for k, v in zip(keys, values)])
In den ersten beiden Fällen wird eine zusätzliche Schicht nicht operativer (daher unnötiger) Berechnungen über die iterierbare Zip-Datei gelegt, und im Fall des Listenverständnisses wird unnötigerweise eine zusätzliche Liste erstellt. Ich würde erwarten, dass alle weniger performant sind, und schon gar nicht mehr.
In 64-Bit-Python 3.8.2 von Nix unter Ubuntu 16.04, geordnet vom schnellsten zum langsamsten:
>>> 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))
gewinnt auch mit kleinen Sätzen von Schlüsseln und Werten, aber bei größeren Sätzen werden die Leistungsunterschiede größer.
Ein Kommentator sagte:
min
scheint ein schlechter Weg zu sein, um die Leistung zu vergleichen. Sicherlichmean
und / odermax
wären viel nützlichere Indikatoren für den tatsächlichen Gebrauch.
Wir verwenden, min
weil diese Algorithmen deterministisch sind. Wir wollen die Leistung der Algorithmen unter den bestmöglichen Bedingungen kennen.
Wenn das Betriebssystem aus irgendeinem Grund hängt, hat es nichts mit dem zu tun, was wir vergleichen möchten. Daher müssen wir diese Art von Ergebnissen von unserer Analyse ausschließen.
Wenn wir mean
diese Art von Ereignissen verwenden , werden unsere Ergebnisse stark verzerrt, und wenn wir sie verwenden, erhalten max
wir nur das extremste Ergebnis - das wahrscheinlichste, das von einem solchen Ereignis betroffen ist.
Ein Kommentator sagt auch:
In Python 3.6.8 ist das Diktatverständnis unter Verwendung von Mittelwerten tatsächlich noch schneller, und zwar um etwa 30% für diese kleinen Listen. Bei größeren Listen (10.000 Zufallszahlen) ist der
dict
Anruf etwa 10% schneller.
Ich nehme an, wir meinen dict(zip(...
mit 10.000 Zufallszahlen. Das klingt nach einem ziemlich ungewöhnlichen Anwendungsfall. Es ist sinnvoll, dass die direktesten Anrufe in großen Datenmengen dominieren, und ich wäre nicht überrascht, wenn die Betriebssystem-Hänge dominieren würden, wenn man bedenkt, wie lange es dauern würde, diesen Test auszuführen und Ihre Zahlen weiter zu verzerren. Und wenn Sie verwenden mean
oder max
ich würde Ihre Ergebnisse für bedeutungslos halten.
Verwenden wir für unsere Top-Beispiele eine realistischere Größe:
import numpy
import timeit
l1 = list(numpy.random.random(100))
l2 = list(numpy.random.random(100))
Und wir sehen hier, dass dict(zip(...
bei größeren Datensätzen tatsächlich um etwa 20% schneller läuft.
>>> 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))
Mikrosekunden für & 1,95 \ pm 0,030 Mikrosekunden für zurück {k: v for k, v in zip(headList, textList)}
. Ersteres würde ich aus Gründen der Lesbarkeit und Geschwindigkeit vorschlagen. Offensichtlich kommt dies zum Argument min () vs mean () für timeit.
min
scheint ein schlechter Weg zu sein, um die Leistung zu vergleichen. Sicherlich mean
und / oder max
wären viel nützlichere Indikatoren für den tatsächlichen Gebrauch.
dict
Anruf etwa 10% schneller.
Versuche dies:
>>> 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 ist der Speicherverbrauch im Vergleich zu wirtschaftlicher zip
.
zip
ist der Speicherverbrauch bereits sparsam. docs.python.org/3/library/functions.html#zip In der Tat kann man sehen , dass six
Anwendungen zip
in Python 3 zu ersetzen , itertools.izip
in 2 Python pythonhosted.org/six .
Sie können auch Wörterbuchverständnisse in Python ≥ 2.7 verwenden:
>>> keys = ('name', 'age', 'food')
>>> values = ('Monty', 42, 'spam')
>>> {k: v for k, v in zip(keys, values)}
{'food': 'spam', 'age': 42, 'name': 'Monty'}
Ein natürlicherer Weg ist die Verwendung des Wörterbuchverständnisses
keys = ('name', 'age', 'food')
values = ('Monty', 42, 'spam')
dict = {keys[i]: values[i] for i in range(len(keys))}
dict
Objekt zu konvertieren . Warum ist es so? Danke, Alter.
Wenn Sie Schlüssel oder Werte transformieren müssen, bevor Sie ein Wörterbuch erstellen, kann ein Generatorausdruck verwendet werden. Beispiel:
>>> adict = dict((str(k), v) for k, v in zip(['a', 1, 'b'], [2, 'c', 3]))
Schauen Sie sich Code Like a Pythonista an: Idiomatic Python .
Mit Python 3.x geht es um das Verständnis von Diktaten
keys = ('name', 'age', 'food')
values = ('Monty', 42, 'spam')
dic = {k:v for k,v in zip(keys, values)}
print(dic)
Mehr zum Diktatverständnis hier , ein Beispiel gibt es:
>>> print {i : chr(65+i) for i in range(4)}
{0 : 'A', 1 : 'B', 2 : 'C', 3 : 'D'}
Für diejenigen, die einfachen Code benötigen und nicht vertraut sind mit zip
:
List1 = ['This', 'is', 'a', 'list']
List2 = ['Put', 'this', 'into', 'dictionary']
Dies kann durch eine Codezeile erfolgen:
d = {List1[n]: List2[n] for n in range(len(List1))}
List1
länger alsList2
for n in range(len(List1))
ist ein Anti-Muster
Die beste Lösung ist immer noch:
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'}
Übertragen Sie es:
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')
Sie können diesen folgenden Code verwenden:
dict(zip(['name', 'age', 'food'], ['Monty', 42, 'spam']))
Stellen Sie jedoch sicher, dass die Länge der Listen gleich ist. Wenn die Länge nicht gleich ist, drehen Sie die Zip-Funktion um die längere.
Ich hatte diesen Zweifel, als ich versuchte, ein grafisches Problem zu lösen. Das Problem, das ich hatte, war, dass ich eine leere Adjazenzliste definieren musste und alle Knoten mit einer leeren Liste initialisieren wollte. Dann dachte ich, ich würde prüfen, ob es schnell genug ist. Ich meine, ob es sich lohnt, eine Zip-Operation durchzuführen eher als einfaches Zuweisungsschlüssel-Wert-Paar. Schließlich ist der Zeitfaktor meistens ein wichtiger Eisbrecher. Also habe ich für beide Ansätze eine zeitliche Operation durchgeführt.
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)}')
Für n_nodes = 10.000.000 bekomme ich,
Iteration: 2.825081646999024 Kurzform: 3.535717916001886
Iteration: 5.051560923002398 Kurzform: 6.255070794999483
Iteration: 6.52859034499852 Kurzform: 8.221581164998497
Iteration: 8.683652416999394 Kurzschrift: 12.599181543999293
Iteration: 11.587241565001023 Kurzform: 15.27298851100204
Iteration: 14.816342867001367 Kurzschrift: 17.162912737003353
Iteration: 16.645022411001264 Kurzschrift: 19.976680120998935
Sie können deutlich sehen, dass nach einem bestimmten Punkt der Iterationsansatz im n-ten Schritt die Zeit übersteigt, die der Kurzansatz im n-1-ten Schritt benötigt.
Hier ist auch ein Beispiel für das Hinzufügen eines Listenwerts in Ihrem Wörterbuch
list1 = ["Name", "Surname", "Age"]
list2 = [["Cyd", "JEDD", "JESS"], ["DEY", "AUDIJE", "PONGARON"], [21, 32, 47]]
dic = dict(zip(list1, list2))
print(dic)
Stellen Sie immer sicher, dass sich Ihr "Schlüssel" (Liste1) immer im ersten Parameter befindet.
{'Name': ['Cyd', 'JEDD', 'JESS'], 'Surname': ['DEY', 'AUDIJE', 'PONGARON'], 'Age': [21, 32, 47]}
Sie können es auch mit einer Liste versuchen, die eine Kombination aus zwei Listen ist;)
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])))
Methode ohne Zip-Funktion
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)}
das nicht funktioniert. Sie müssen ausdrücklich erklären alsdict(...)