0%

Dictionaries und andere Sammlungen · Übung

Eine Liste von Datensätzen durchsuchen

Ein Katalog ist nützlich, wenn ein Programm einen Datensatz anhand eines Feldes finden kann.

catalog = [
    {"title": "Kindred", "year": 1979},
    {"title": "Dune", "year": 1965},
]

Du kannst die Liste nicht nach "Dune" als Schlüssel fragen. Die Liste enthält Dictionaries, also durchsuche einen Datensatz nach dem anderen:

for item in catalog:
    if item["title"] == "Dune":
        print(item)

Die Suche in eine Funktion verlagern

Eine Suchfunktion kann das passende Dictionary zurückgeben:

def find_by_title(catalog, query):
    for item in catalog:
        if item["title"] == query:
            return item

    return None

Wenn ein Titel übereinstimmt, beendet das erste return die Funktion sofort und gibt dieses Dictionary an den aufrufenden Code zurück.

Wenn die Schleife ohne Treffer endet, erreicht die Ausführung return None. None drückt ausdrücklich aus: „kein passender Datensatz“.

Kapitel 8 hat bereits gezeigt, dass return den aktuellen Funktionsaufruf beendet und dass eine Funktion ohne nutzbares Ergebnis None liefert. Hier wird dieses Verhalten Teil der Vereinbarung für eine Suche:

  • bei einem Treffer wird ein Dictionary zurückgegeben;

  • ohne Treffer wird None zurückgegeben.

Die beiden Pfade unten zeigen, warum das abschließende return None hinter die Schleife gehört: Ein Treffer führt zum vorzeitigen Verlassen, während bei einer Suchanfrage ohne Treffer zuerst jeder Datensatz geprüft werden muss.

Zwei Suchpfade vergleichen die Datensätze der Reihe nach. Dune gibt den passenden Datensatz sofort zurück, während Solaris das Ende erreicht und None zurückgibt.

Beide Seiten bereinigen

Bei der Eingabe können Groß- und Kleinschreibung abweichen oder umgebende Leerzeichen vorkommen. Bereinige die Suchanfrage einmal:

clean_query = query.strip().lower()

Baue diese Bereinigung in die vollständige Funktion ein und vergleiche das Ergebnis mit einer kleingeschriebenen Version jedes gespeicherten Titels:

def find_by_title(catalog, query):
    clean_query = query.strip().lower()

    for item in catalog:
        if item["title"].lower() == clean_query:
            return item

    return None

Der ursprüngliche Titel im Dictionary bleibt unverändert.

Das Ergebnis prüfen

Verwende is not None, um den Fall mit einem Treffer zu behandeln:

match = find_by_title(catalog, "  DUNE ")

if match is not None:
    print(match["year"])
else:
    print("No matching title.")

is None und is not None sind die üblichen Prüfungen für diesen einen besonderen Wert.

Was enthält match?

def find_by_name(records, query):
    for record in records:
        if record["name"].lower() == query.strip().lower():
            return record
    return None

places = [
    {"name": "Kyoto", "country": "Japan"},
    {"name": "Lima", "country": "Peru"},
]

match = find_by_name(places, " lima ")

Aufgabe

Vervollständige find_by_title(catalog, query).

Die Funktion muss:

  1. query mit .strip().lower() bereinigen;

  2. die Dictionary-Datensätze in catalog in einer Schleife durchlaufen;

  3. die bereinigte Suchanfrage mit jedem kleingeschriebenen Titel vergleichen;

  4. das passende Dictionary sofort zurückgeben;

  5. nach der Schleife None zurückgeben, wenn nichts übereingestimmt hat.

Behalte den vorhandenen Aufruf und die Ergebnisprüfung bei.

Erwartete Ausgabe:

Found: Dune (1965)

Das Bewertungssystem ruft deine Funktion außerdem mit einem anderen Titel und mit einem nicht vorhandenen Titel auf.