Dictionaries
Problem
Um mehrere Listen zu verknüpfen, müssen wir jeweils den passenden Eintrag in einer Liste in der anderen suchen. Beispielsweise möchten wir die Postleitzahl zu den Schweizer Gemeinden finden, nur leider sind die Postleitzahlen in einer anderen Datei gespeichert (plz.csv
). Wenn wir jedes Mal die ganze Liste durchsuchen müssen, dauert dies ziemlich lange. Geht das auch schneller?
Wie wir wissen, können wir in einem (sortierten) Wörterbuch (Diktionär) effizient suchen:
- Der Suchbereich wird fortlaufend halbiert (s.a. Binäre Suche in Suchen und Sortieren)
- Bei $n$ Einträgen benötigt die Suche nach einem Element nur $log_2(n)$ Zugriffe, also
- $10$ Zugriffe für $1024$ Elemente,
- $20$ Zugriffe für $1024\cdot1024 \approx 1Mio$,
- $30$ Zugriffe für $1024\cdot1024\cdot1024 \approx 1Mia$
Syntax
Es wäre schön, hätten wir eine Datenstruktur, die das für uns erledigt… zum Glück gibt es sie: Dictionary (oft dict abgekürzt).
- Ein Dictionary stellt eine Sammlung von
Schlüssel : Wert
Paaren dar (oderkey : value
). - Erlaubt direkten Zugriff auf jedes Element mit dem gewünschten Schlüssel.
- In Wahrheit benützt sie nicht binäre Suche, sondern eine noch schnellere Zugriffsart: Hashtabelle.
Ein leeres Dictionary wird mit geschweiften Klammern erzeugt:
zip_codes = {}
Alternativ können auch bereits Einträge von der Form key : value
eingetragen werden:
zip_codes = { 'Romanshorn' : 8590, 'Egnach' : 9322 }
Auf ein bestimmtes Element kann über eckige Klammern und den Schlüssel (key) zugegriffen werden. Die Syntax ist die gleiche wie beim Listenzugriff, nur verwenden wir statt dem Index den Schlüssel.
plz = zip_codes['Romanshorn'] print(plz)
8590
Ein neues Element kann mit derselben Syntax angelegt werden - ist der Schlüssel bereits vorhanden, wird der Wert überschrieben:
zip_codes['Amriswil'] = 8580 # Legt ein neues Key-Value-Pair an. zip_codes['Romanshorn'] = 8591 # Überschreibt den bestehenden Eintrag für Romanshorn print(zip_codes)
{'Romanshorn': 8591, 'Egnach': 9322, 'Amriswil': 8580}
Mit dem in
Schlüsselwort kann herausgefunden werden, ob ein Schlüssel im Dictionary vorhanden ist:
print('Romanshorn' in zip_codes)
True
print('St. Gallen' in zip_codes)
False
Wir können eine for
-Schleife über die Keys in einem Dictionary schreiben:
for town in zip_codes: print(town)
Romanshorn Egnach Amriswil
Möchten wir in der Schleife sowohl Key als auch Value haben, verwenden wir die items()
Funktion:
for town, plz in zip_codes.items(): print(plz, town)
8591 Romanshorn 9322 Egnach 8580 Amriswil
Aufgabe 1: Dictionary Syntax
Schreibe Code wie die obigen Beispiele, um eine Sammlung von Postleitzahlen anzulegen.
Wie müsste man vorgehen, wenn wir sowohl ein Mapping von Ortsnamen zu Postleitzahlen als auch umgekehrt von Postleitzahlen zu Ortsnamen haben möchten?
Aufgabe 2: CSV in ein Dictionary einlesen
Lies die Datei plz.csv ein und erstelle daraus ein Dictionary von Ortsnamen zu Postleitzahl.
Die Daten sehen so aus:
PLZ,Ort,Kanton 1000,Lausanne,Waadt 1005,Lausanne,Waadt 1008,Prilly,Waadt 1009,Pully,Waadt ...
Hinweise:
- Die PLZ steht zuerst, also an
values[0]
- Der Ort ist an zweiter Stelle, also
values[1]
- Wir wollen ein umgekehrtes Dictionary von Ortsnamen zu PLZ.
- Ein Ortsnamen kann mehrere Postleitzahlen haben - wir möchten immer die kleinste behalten (also
1000
für Lausanne, nicht1005
).
Aufgabe 3: Zwei Datasets kombinieren
Kombiniere die Daten zu den Schweizer Gemeinden (aus Data Processing A6) mit den Postleitzahl-Daten: Was ist PLZ der kleinsten Schweizer Gemeinde? Der flächenmässig grössten Gemeinde?
Mehr zu Dictionaries
Du willst mehr über Dictionaries wissen und selber eines programmieren? Schau hier!
Nächstes Kapitel
Weiter mit Kartendaten mit Python.