Woche 12#
Entwicklung einer Lösung im Detail: Beispiel#
gegeben:
in Dict
EXAMINER, das zu jedem Prüfer-Kürzel Infos zur Person gibt.
EXAMINER = {
"mm": { "FULLNAME": "Mustermann, Max", "FACULTY": "x_if" },
"em": { "FULLNAME": "Musterfrau, Erika", "FACULTY": "x_if" },
"cm": { "FULLNAME": "Maier, Charly", "FACULTY": "soz" } }
gesucht:
ein Dict, das zu jeder Fakultät die zugehörigen Prüfer angibt, und das z.B. so aussehen könnte:
# FACULTY_EXAMINER_dict
{'soz': {'cm'}, 'x_if': {'em', 'mm'}}
Praxisbezug#
Oben ist ein Dict angegeben. Alternativ zum Dict werden wir in der Realität unsere Informationen auch aus einer CSV- oder einer Excel-Datei in ein DataFrame einlesen wollen:
df = pd.read_csv("examiners.csv")
Weil wir diese CSV-Datei nicht haben, können wir das DataFrame auch aus unserem Dict erzeugen:
import pandas as pd
df = pd.DataFrame.from_dict(EXAMINER, orient="index")
df.index.name = "EXAMINER"
df
| FULLNAME | FACULTY | |
|---|---|---|
| EXAMINER | ||
| mm | Mustermann, Max | x_if |
| em | Musterfrau, Erika | x_if |
| cm | Maier, Charly | soz |
Dieses df können wir wieder in obiges Python-Dict zurückverwandeln.
Für den Hin- und Rückweg gibt es verschiedene Möglichkeiten. Diese Doku dazu sollte man kennen:
https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.from_dict.html
https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.to_dict.html
e2 = df.to_dict(orient="index")
e2
{'mm': {'FULLNAME': 'Mustermann, Max', 'FACULTY': 'x_if'},
'em': {'FULLNAME': 'Musterfrau, Erika', 'FACULTY': 'x_if'},
'cm': {'FULLNAME': 'Maier, Charly', 'FACULTY': 'soz'}}
for k,v in e2.items():
print(k,v["FACULTY"])
mm x_if
em x_if
cm soz
Wir können auch programmatisch nachweisen, dass der Roundtrip funktioniert:
assert EXAMINER == e2
Die Aufgabenstellung im Detail#
Typische Aufgabe: Umsortieren des Dicts, Beispiel: Welche Examiners gibt es in der Fakultät x_if?
Unser Weltwissen sagt uns, dass eine Fakultät typischerweise mehrere Prüfer hat. Im Ergebnis wollen wir zu jeder Fakultät eine Menge der zugehörigen Prüfer anlegen. Das ist typischerweise ein Dict.
Herangehensweise ungefähr:
Welche Fakultäten gibt es? Lege eine Menge
FACULTY_setaller Fakultäten an.Definiere die Datenstruktur des Ergebnisses: Ein Dict
FACULTY_EXAMINER_dict, das für jede Fakultät die Menge der zugehörigen Prüfer enthält.Gehe das Dict
EXAMINERnochmals durch: In welcher Fakultät ist ein Prüfer? Füge den Prüfer zur Menge der Prüfer der jeweiligen Fakultät hinzu.
FACULTY_set#
Faustregel: Es könnte geschickt sein, die Menge aller Fakultäten anzulegen – auch wenn wir noch nicht im Detail wissen, was wir weiter damit machen werden.
Faustregel: Solange uns nichts besseres einfällt, verwenden wir die Grundstruktur der Listenbearbeitung.
Einen Anfang machen mit https://de.wikipedia.org/wiki/Boilerplate-Code :
#Ergebnis-Variable initialisieren
FACULTY_set = set()
for kuerzel, spalten in EXAMINER.items():
print(f"{kuerzel=}\n {spalten=}")
kuerzel='mm'
spalten={'FULLNAME': 'Mustermann, Max', 'FACULTY': 'x_if'}
kuerzel='em'
spalten={'FULLNAME': 'Musterfrau, Erika', 'FACULTY': 'x_if'}
kuerzel='cm'
spalten={'FULLNAME': 'Maier, Charly', 'FACULTY': 'soz'}
Wir haben ein Dict von Dicts. Also benötigen wir vermutlich eine innere Schleife:
#Ergebnis-Variable initialisieren
FACULTY_set = set()
for kuerzel, spalten in EXAMINER.items():
print(f"\n{kuerzel=}")
for spalte, wert in spalten.items():
print(f" {spalte=},\t{wert=}")
kuerzel='mm'
spalte='FULLNAME', wert='Mustermann, Max'
spalte='FACULTY', wert='x_if'
kuerzel='em'
spalte='FULLNAME', wert='Musterfrau, Erika'
spalte='FACULTY', wert='x_if'
kuerzel='cm'
spalte='FULLNAME', wert='Maier, Charly'
spalte='FACULTY', wert='soz'
Die Spalte FACULTY enthält den Wert, den wir in unsere Ergebnis-Variable FACULTY_set aufnehmen wollen.
FACULTY_set = set()
for kuerzel, spalten in EXAMINER.items():
print(f"\n{kuerzel=}")
for spalte, wert in spalten.items():
print(f" {spalte=},\t{wert=}")
if spalte == "FACULTY":
FACULTY_set.add( wert )
FACULTY_set
kuerzel='mm'
spalte='FULLNAME', wert='Mustermann, Max'
spalte='FACULTY', wert='x_if'
kuerzel='em'
spalte='FULLNAME', wert='Musterfrau, Erika'
spalte='FACULTY', wert='x_if'
kuerzel='cm'
spalte='FULLNAME', wert='Maier, Charly'
spalte='FACULTY', wert='soz'
{'soz', 'x_if'}
Wir sehen – eigentlich schon von Anfang an – dass es auch etwas kürzer geht:
FACULTY_set = set()
for kuerzel, spalten in EXAMINER.items():
FACULTY_set.add( spalten["FACULTY"])
FACULTY_set
{'soz', 'x_if'}
Diese Grundstruktur lässt sich auch mechanisch in eine (hier: Set-) Comprehension verwandeln. Mit etwas Erfahrung kann man auch folgende Zeile sofort hinschreiben:
FACULTY_set = { spalten["FACULTY"] for spalten in EXAMINER.values() }
FACULTY_set
{'soz', 'x_if'}
FACULTY_EXAMINER_dict#
Faustregel: Wieder mit der Grundstruktur beginnen.
Ergebnis initialisieren: Ein Dict mit den Elementen aus FACULTY_set als Keys und leeren Mengen als Values.
FACULTY_EXAMINER_dict = { f: set() for f in FACULTY_set }
FACULTY_EXAMINER_dict
{'x_if': set(), 'soz': set()}
Und jetzt die Schleife:
for kuerzel, spalten in EXAMINER.items():
# aus welcher Fakultät stammt der Prüfer mit dem Kürzel `kuerzel` ?
fak = spalten["FACULTY"]
# zum Ergebnis-Set hinzufügen
print(f"Prüfer {kuerzel=} stammt aus der Fakultät {fak=}")
FACULTY_EXAMINER_dict[fak].add( kuerzel )
FACULTY_EXAMINER_dict
Prüfer kuerzel='mm' stammt aus der Fakultät fak='x_if'
Prüfer kuerzel='em' stammt aus der Fakultät fak='x_if'
Prüfer kuerzel='cm' stammt aus der Fakultät fak='soz'
{'x_if': {'em', 'mm'}, 'soz': {'cm'}}
Zusammenfassung#
So sieht eine kurze, konzise Lösung aus:
# Stammdaten
EXAMINER = {
"mm": { "FULLNAME": "Mustermann, Max", "FACULTY": "x_if" },
"em": { "FULLNAME": "Musterfrau, Erika", "FACULTY": "x_if" },
"cm": { "FULLNAME": "Maier, Charly", "FACULTY": "soz" } }
# Welche Fakultäten haben wir?
FACULTY_set = { spalten["FACULTY"] for spalten in EXAMINER.values() }
# Initialisiere das Lösungs-Dict:
# Schlüssel ... die Elemente aus der Menge der Fakultäten
# Values: (noch) leere Mengen
FACULTY_EXAMINER_dict = { f: set() for f in FACULTY_set }
# Die Values im Lösungs-Dict einsammeln
for kuerzel, spalten in EXAMINER.items():
FACULTY_EXAMINER_dict[ spalten["FACULTY"] ].add( kuerzel )
# Lösung anzeigen
FACULTY_EXAMINER_dict
{'x_if': {'em', 'mm'}, 'soz': {'cm'}}