Grundstruktur Listenbearbeitung#

Hinweis 2023-10-13: Viele der Beispiele lassen sich mit einer List Comprehension wesentlich eleganter formulieren. Aber eine List Comprehension versteht man nur, wenn man die Beispiele verstanden hat.

  • Also zunächst mal “zu Fuß” mit einer expliziten for-Schleife und manuellem Konstruieren der Ergebnis-Liste.

  • Später dann die Aufgabe “Stellen Sie die bereits gelöste Aufgabe mit einer List-Comprehension dar!”

Anwendungsbeispiel#

Gegeben: eine Liste von Klausurnoten.

  • z.B. [ 1, 2, 5, 3, 1]

Annahme: Studierende dürfen Fehlversuche streichen.

Gesucht: Eine Liste sowie der Notenschnitt von allen bestandenen Klausuren.

  • z.B. [ 1, 2, 3, 1], Schnitt: 1.75

# Eingabe
Liste_input = [ 1, 2, 5, 3, 1]

# Ausgabe
Liste_output = []
Summe = 0

# Objekt nimmt nacheinander jeden Wert aus der Eingabeliste an
for x in Liste_input:
    
    # erfüllt das x alle gewünschten Eigenschaften?
    if x < 5:
        
        # x an die Ausgabeliste anhängen
        Liste_output.append( x )
        
        # x zur Summe hinzuaddieren
        Summe += x

Schnitt = Summe / len( Liste_output )

print("übernommene Noten:", Liste_output, "Schnitt:", Schnitt )
übernommene Noten: [1, 2, 3, 1] Schnitt: 1.75

Als Vorschau dasselbe mit einer List-Comprehension:

# List Comprehension
Liste_output = [ x for x in Liste_input if x < 5 ]

Schnitt = sum( Liste_output ) / len( Liste_output )

# modernere Printsyntax mit f-String
print(f"übernommene Noten: {Liste_output} Schnitt: {Schnitt}" )
übernommene Noten: [1, 2, 3, 1] Schnitt: 1.75

Erweiterung: “gut” ist Note 2#

Die obige Grundstruktur lässt sich nun erweitern. So seien die Klausurnoten nicht nur durch Zahlen, sondern alternativ auch durch Text gegeben.

  • z.B. Liste_input = [ 1, 2, 5, "krank", "befriedigend", "im Ausland", "mit Auszeichnung"]

Lösungsansatz: Bilde Text über ein dict auf eine Note ab.

  • z.B. Note_aus_Text = {"sehr gut": 1, "mit Auszeichnung": 1, ...: ... }

Note_aus_Text = {"sehr gut": 1, "gut": 2,
                 "befriedigend": 3, "ausreichend": 4,
                 "mangelhaft": 5, "ungenügend": 6,
                 "mit Auszeichnung": 1,
                 "krank": None}

Liste_input = [ 1, 2, 5, "krank", "befriedigend", "im Ausland", "mit Auszeichnung"]

Liste_output = []
Summe = 0

for x in Liste_input:
    
    # haben wir eine Zahl?
    if isinstance(x, (float, int)):
        Note = x
    
    # oder haben wir einen uns bekannten Text?
    elif x in Note_aus_Text:
        Note = Note_aus_Text[x]
    
    # nichts erkannt
    else:
        Note = None
        
    if Note != None and Note <= 4:
        Liste_output.append(Note)
        Summe += Note

Schnitt = Summe / len(Liste_output)

print("übernommene Noten:", Liste_output, "Schnitt:", Schnitt )
übernommene Noten: [1, 2, 3, 1] Schnitt: 1.75

Slicing#

minimale Einführung hier, quasi Vorausschau, nur um das Sprachelement zu zeigen. Ausführlicher z.B. https://note.nkmk.me/en/python-slice-usage/

l = [ 'a', 'b', 'c', 'd', 'e', 'f']
l[0:3]
['a', 'b', 'c']
l[0] # die Zählung beginnt mit 0
'a'
l[0:2] # wählt l[0] und l[1] aus, denn l[2] ist nicht mehr 'drinn'
['a', 'b']
l[0:5:2] # l[0] bis l[4] in Zweierschritten
['a', 'c', 'e']
[ 'a', 'b', 'c', 'd', 'e', 'f'][0:5:2] # ein Slice einer direkt angegebenen Liste
['a', 'c', 'e']

Insbeondere auch Strings sind sliceables:

s = "abcdef"
s[0:5:2]
'ace'

Lernerfolskontrolle: Erkläre die Syntax

[0,1,2][0:1:2]

Was kommt ‘raus?’

Verallgemeinerung#

Verallgemeinerung der Grundstruktur “durch eine Liste durchgehen”: Durchgehen kann man auch durch ein

  • dict

  • Generator

    • range()

    • Zufallszahlen

Durchgehen durch ein dict#

  • z.B. { "Januar": 31, "Februar": 28, "März": 31 }

In einem Dict haben wir zur Verfügung die Methoden

  • keys()

  • values()

  • items()

Beispiele:

# Tage im Monat
TiM = { "Januar": 31, "Februar": 28, "März": 31, "April": 30, "Mai": 31 }

for x in TiM:
    print(x)
Januar
Februar
März
April
Mai
for x in TiM.keys():
    print(x)
Januar
Februar
März
April
Mai
for x in TiM.values():
    print(x)
31
28
31
30
31

Interessant ist die Methode items(). Sie gibt zwei Werte zurück!

# x zeigt hier auf ein Zweitupel 
for x in TiM.items():
    print( x[0:2] )
('Januar', 31)
('Februar', 28)
('März', 31)
('April', 30)
('Mai', 31)
# hier werden die 2 Rückgabewerte von items() direkt den zwei Variablen zugewiesen
for ( p, q ) in TiM.items():
    print("p:", p, "q:", q)
p: Januar q: 31
p: Februar q: 28
p: März q: 31
p: April q: 30
p: Mai q: 31
# die Klammern kann man auch weglassen
for p, q in TiM.items():
    print("p:", p, "q:", q)
p: Januar q: 31
p: Februar q: 28
p: März q: 31
p: April q: 30
p: Mai q: 31

Durchgehen durch eine automatisch generierte Liste von Zahen: range()#

Erklärung zu range(): Googeln hilft, Erklärungen gibt es im Netz zuhauf. Hier nur ein Beispiel:

for i in range(1, 5):
    print(i)
    
1
2
3
4

Man bemerke: Die erste Zahl ist inkludiert, die zweite excludiert.

Liste von Zufallszahlen#

siehe Doku: https://docs.python.org/3/library/random.html

import random

# erzeuge 5 Zufallszahlen zwischen 2000 und 2024
for i in range(5):
    print(random.randrange(2000, 2024))
2012
2018
2000
2013
2012

Beispielaufgaben#

Beispielaufgaben unterschiedlicher Schwierigkeit, die aber alle mit dem Grundmuster plus ein paar einfache Operationen lösbar sind.

Häufigkeit von Elementen einer Liste#

Gegeben: Eine Liste z.B. von Buchstaben

Buchstabenliste = list("Hallo Welt!")
print(Buchstabenliste)
['H', 'a', 'l', 'l', 'o', ' ', 'W', 'e', 'l', 't', '!']
x = {"a": 7 }
x["a"] = 1000
x
{'a': 1000}
x["b"] = 2000
x
{'a': 1000, 'b': 2000}
# das erzeugt einen Fehler
# x["c"] += 1

# Recherche-Aufgabe: Statt den Fehler abzufangen 
# kann man einen Default-Wert angeben: Wie? 

gesucht: ein Dict, das für jeden Kleinbuchstaben die Häufigkeit angibt.

Haeufigkeit = {}

for b in Buchstabenliste:
    
    if b in "abcdefghijklmnopqrstuvwxyzöäüß":
        
        # Ist der key b neu für uns?
        # key neu anlegen und Zähler mit 1 initialisieren
        if b not in Haeufigkeit:
            Haeufigkeit[b] = 1
            
        # oder kennen wir den key schon?
        # Zähler um 1 erhöhen!
        else:
            Haeufigkeit[b] += 1
    
print(Haeufigkeit)
{'a': 1, 'l': 3, 'o': 1, 'e': 1, 't': 1}

Set aus Liste erzeugen#

Dafür gibt es eigentlich die Funktion set(). Aber wir kennen diese Funktion noch nicht, wir wollen sie programmieren.

Gegeben: Eine Liste L1 von Zahlen.

Gesucht: eine zweite Liste L2, in der jede Zahl aus L1 nur einmal vorkommt. Die Reihenfolge ist egal; insbesondere muss L2 nicht sortiert sein.

Tupel in einer Liste bearbeiten: Zeitabschnitte#

Gegeben:

  • eine Liste des Beginns und Ende wichtiger Zeitabschnitte. Bei Zeitabschnitten, die bis heute andauern, ist als Ende None angegeben.

    • z.B. K = [ (1939, 1945), (1955, 1975), (1979, 1989), (1980, 1988), (2003, 2011), (1991, 2001), (2011, 2011), (2014, None),  (2014, None), (1988, None), (2022, None), (2023, None) ]

Gesucht:

  • Eine Liste von Dreitupeln, bei denen zu jedem Zeitabschnitt auch die Dauer angegeben ist.

    • z.B. K_Dauer = [ (1939, 1945, 7),  ..., (2011, 2011, 1), (1988, None, None)  ]

  • Eine Menge des Anfangs der Zeitabschnitte, die bis heute andauern.

    • z.B. K_andauernd = { 2014, 1988, 2022 }