mitmario.dev

Zählen mit Dictionaries

Python Sandbox 4 Min Lesezeit 4 BeispieleLektion 3 von 7

Am Kaffeestand beim Vereinsfest willst du wissen, wie oft Kaffee bestellt wurde, wie oft Tee und wie oft Kakao. Und vielleicht bestellt nachher noch jemand eine Limo, an die vorher keiner gedacht hat.

Ein einzelner Zähler, der vor der Schleife auf null steht und darin um eins wächst, reicht dafür nicht. Für jedes Getränk eine eigene Variable geht aber auch nicht. Du weißt ja vorher gar nicht, welche Getränke es geben wird.

Mit einem Dictionary geht es. Jedes Getränk bekommt seinen eigenen Zähler, als Wert unter seinem Namen, und ein Getränk, das neu auftaucht, bekommt eben einen neuen.

Das Zählmuster

Ein Zähler je Getränk
bestellungen = ["Kaffee", "Tee", "Kaffee", "Kakao", "Kaffee", "Tee"]
zaehler = {}
for getraenk in bestellungen:
    zaehler[getraenk] = zaehler.get(getraenk, 0) + 1
print(zaehler)

Die eine Zeile in der Schleife ist schon das ganze Muster. Python rechnet erst die rechte Seite des Gleichheitszeichens aus und legt das Ergebnis dann links ab. In dieser Reihenfolge liest man die Zeile auch am besten.

  1. zaehler.get(getraenk, 0) holt den bisherigen Stand dieses Getränks. Ist es noch gar nicht da, ist der Stand 0, denn das ist der Standardwert von get.
  2. + 1 zählt die Bestellung dieser Runde dazu.
  3. zaehler[getraenk] = … legt den neuen Stand unter dem Namen ab. Beim ersten Kaffee entsteht so ein neues Paar, bei jedem weiteren bekommt das vorhandene einen neuen Wert.

Es ist dasselbe wie anzahl += 1, ausgeschrieben anzahl = anzahl + 1. Nur steht vor dem Gleichheitszeichen kein fester Name, sondern ein Platz im Dictionary, der vom Getränk der Runde abhängt.

Wenn du das Beispiel im Reiter Debug aufzeichnest, siehst du das Dictionary wachsen. Die Schleife springt zwischen Zeile 3 und Zeile 4 hin und her, und vor jeder Zeile 4 steht da, wie weit gezählt ist. Erst {}, dann {'Kaffee': 1}, dann {'Kaffee': 1, 'Tee': 1}. In der vierten Runde ist getraenk zum ersten Mal 'Kakao', und einen Schritt später hat das Dictionary ein drittes Paar. Am Ende stehen drei Zähler darin. Mehr Variablen als zaehler waren dafür nicht nötig.

Plus eins auf nichts

Plus eins auf nichts
bestellungen = ["Kaffee", "Tee", "Kaffee"]
zaehler = {}
for getraenk in bestellungen:
    zaehler[getraenk] += 1
print(zaehler)

Die kürzere Form liegt nahe, und sie geht schief. zaehler[getraenk] += 1 heißt ausgeschrieben zaehler[getraenk] = zaehler[getraenk] + 1, und rechts steht ein Lesen mit eckigen Klammern. Beim allerersten Kaffee gibt es den Schlüssel noch nicht. Also kommt KeyError: 'Kaffee', gleich in der ersten Runde. Diese Lücke füllt der Standardwert von get.

Dasselbe mit in

Dasselbe mit in
bestellungen = ["Kaffee", "Tee", "Kaffee", "Kakao", "Kaffee", "Tee"]
zaehler = {}
for getraenk in bestellungen:
    if getraenk in zaehler:
        zaehler[getraenk] += 1
    else:
        zaehler[getraenk] = 1
for getraenk in sorted(zaehler):
    print(f"{getraenk}: {zaehler[getraenk]}")

Ist dir die eine Zeile zu dicht, schreibst du es mit in und if. Gibt es das Getränk schon, wird sein Zähler um eins größer. Sonst fängt es bei 1 an. Hier ist += 1 erlaubt, weil es in dem Zweig steht, in dem der Schlüssel sicher da ist.

Das Ergebnis ist dasselbe, und beide Formen sind richtig. Die mit get ist kürzer, deshalb sieht man sie in fremdem Code am häufigsten.

In der zweiten Schleife wird das Ergebnis sortiert ausgegeben. Dass Kakao vor Tee steht, liegt am Alphabet und nicht an den Bestellungen.

Python bringt fürs Zählen übrigens ein fertiges Werkzeug mit, Counter (Zähler). Damit passt die ganze Schleife in eine Zeile. Es kommt in Lektion 10.1, wenn es um die Werkzeuge geht, die Python von Haus aus mitbringt, und im Inneren tut es nichts anderes als dieses Muster.

Der Wörterzähler aus Lektion 1.1

Der Wörterzähler aus Lektion 1.1
text = """Wer den letzten Kaffee nimmt, kocht neuen Kaffee.
Wer den letzten Becher nimmt, spült ihn auch."""

zaehler = {}
for wort in text.lower().split():
    wort = wort.strip(".,")
    zaehler[wort] = zaehler.get(wort, 0) + 1

for wort, anzahl in zaehler.items():
    if anzahl > 1:
        print(wort, anzahl)

Ganz am Anfang des Kurses stand ein Programm mit dem Versprechen, dass du es sechs Abschnitte später liest wie einen Einkaufszettel. Hier ist es noch einmal, unverändert. Inzwischen kennst du jedes Teil davon.

  • Der Text steht in drei Anführungszeichen, weil er über zwei Zeilen geht.
  • text.lower().split() macht alles klein und zerlegt den Text an Leerraum in Wörter.
  • wort.strip(".,") nimmt Punkt und Komma vom Rand.
  • Die Zeile mit get ist das Zählmuster von oben.
  • Die zweite Schleife geht mit items() durch Wort und Anzahl und gibt nur aus, was mehr als einmal vorkommt.

Heraus kommen fünf Wörter, jedes zweimal: wer, den, letzten, kaffee und nimmt. Am unscheinbarsten ist dabei die Zeile mit strip. Ohne sie stünde nimmt, mit seinem Komma in der Ausgabe, und kaffee würde ganz fehlen, weil es einmal ohne Satzzeichen im Text steht und einmal mit Punkt, und kaffee. wäre für das Dictionary ein eigenes Wort mit einem eigenen Zähler.

Was die Aufgabe will

Ein Verein fragt seine Mitglieder, wohin der nächste Ausflug gehen soll, und jede Antwort ist eine Zeile in einer Datei. Die Antworten wurden von Hand abgetippt und sind entsprechend nicht ganz einheitlich geschrieben. Gezählt werden soll, wie oft jedes Ziel genannt wurde. Ausgegeben werden die Ziele nach dem Alphabet, jedes mit seiner Anzahl.

Zum Mitnehmen

Mit einem Dictionary zählst du viele Dinge auf einmal, jedes unter seinem eigenen Namen, und zwar mit zaehler[ding] = zaehler.get(ding, 0) + 1. Beim allerersten Mal gibt es den Schlüssel noch nicht, und dafür ist der Standardwert 0 da. Mit += 1 allein gäbe es an der Stelle einen KeyError.

Jetzt du

Basis Konto, kostenlos

Zu dieser Lektion gehört eine Aufgabe. Du schreibst den Code selbst, und nach jedem Lauf sagt dir eine Prüfliste, was schon stimmt.

Dafür brauchst du das Basis Konto. Es kostet nichts, und ein Passwort gibt es auch nicht.

In diesem Kurs läuft dein Code auf einem Server. Dafür hat das Basis Konto 1 Stunde im Monat, mehr Zeit gibt es mit dem Premium Konto.

Was in dieser Lektion steckt

  • Artikel mit 4 Beispielen zum Ausprobieren

    Steht hier, ohne Konto lesbar.

  • Aufgabe, dein Code läuft auf einem Server

    Öffnet sich mit dem Basis Konto.