demo_2023-12-15#

Brüche ausrechnen#

gegeben: Eine Liste von Brüchen als String. Gesucht: Ein Dict, das zu den Bruchzahlen den Wert als Zahl angibt.

brueche_bsp = [ "1/4", "2/5", "3/10", "1/4" ]
brueche_bsp_werte = { "1/4": 0.25, "2/5": 0.4 }

Ansatz 1, erst mal das Detail anschauen: bottom up#

b = "1/4"
b_split = b.split("/")
b_split
['1', '4']
zaehler = int(b_split[0])
nenner = int(b_split[1])
b_value = zaehler / nenner
b_value
0.25

dann das Detail in eine Schleife einarbeiten#

ergebnis = {}

for b in brueche_bsp:
    b_split = b.split("/")
    zaehler = int(b_split[0])
    nenner = int(b_split[1])
    b_value = zaehler / nenner
    
    # print(type(b), b, b_split, nenner, zaehler)
    print(f"{type(b)=}, {b=}, {b_split=}, {nenner=}, {zaehler=}, {b_value=}")
    ergebnis[b] = b_value
type(b)=<class 'str'>, b='1/4', b_split=['1', '4'], nenner=4, zaehler=1, b_value=0.25
type(b)=<class 'str'>, b='2/5', b_split=['2', '5'], nenner=5, zaehler=2, b_value=0.4
type(b)=<class 'str'>, b='3/10', b_split=['3', '10'], nenner=10, zaehler=3, b_value=0.3
type(b)=<class 'str'>, b='1/4', b_split=['1', '4'], nenner=4, zaehler=1, b_value=0.25
ergebnis
{'1/4': 0.25, '2/5': 0.4, '3/10': 0.3}

zweiter Ansatz: dop town#

Darstellung hier in Schritten: Jede Zelle ist ein Schritt. Ausgangspunkt:

brueche = [ "1/4", "2/5", "3/10", "1/4" ]

Daraus wollen wir das Ergebnis-Dict herstellen. Zuerst mal mit ... als Platzhalter:

brueche = [ "1/4", "2/5", "3/10", "1/4" ]
ergebnis = { b: ... for b in brueche }
ergebnis
{'1/4': Ellipsis, '2/5': Ellipsis, '3/10': Ellipsis}

Statt ... benötigen wir Code, der einen String wie z.B. "1/4" in einen Ausdruck wie z.B. 1/4 umwandelt. Am einfachsten geht das, indem wir eine Funktion definieren.

Auch diese Funktion entwickeln wir schrittweise. Zunächst geht es nur um das Einbauen der Funktion, die Funktion selbst übergibt erst mal nur unverändert ihren Parameter (dann sehen wir, was wür übergeben haben).

brueche = [ "1/4", "2/5", "3/10", "1/4" ]

def bruchwert(x):
    return x

ergebnis = { b: bruchwert(b) for b in brueche }
ergebnis
{'1/4': '1/4', '2/5': '2/5', '3/10': '3/10'}

Jetzt arbeiten wir an bruchwert(x). Wir versuchen, den String im Parameter x kleinzuarbeiten. Es bietet sich ein x.split("/") an.

brueche = [ "1/4", "2/5", "3/10", "1/4" ]

def bruchwert(x):
    return x.split("/")

ergebnis = { b: bruchwert(b) for b in brueche }
ergebnis
{'1/4': ['1', '4'], '2/5': ['2', '5'], '3/10': ['3', '10']}

Wir sehen: Der Bruch ist jetzt schön in zwei Teile zerlegt. Aber noch sind es 2 Strings und nicht 2 Integer, welch letztere wir eigentlich benötigen. Weil wir List Comprehension lieben, können wir die auch hier gut verwenden.

brueche = [ "1/4", "2/5", "3/10", "1/4" ]

def bruchwert(x):
    return [ int(zahlstring) for zahlstring in x.split("/") ]

ergebnis = { b: bruchwert(b) for b in brueche }
ergebnis
{'1/4': [1, 4], '2/5': [2, 5], '3/10': [3, 10]}

Statt nur eine Liste zurückzugeben, können wir das auch “semantischer”, aussagekräftiger gestalten:

brueche = [ "1/4", "2/5", "3/10", "1/4" ]

def bruchwert(x):
    x_split = [ int(zahlstring) for zahlstring in x.split("/") ]
    zaehler = x_split[0]
    nenner = x_split[1]
    return zaehler, nenner

ergebnis = { b: bruchwert(b) for b in brueche }
ergebnis
{'1/4': (1, 4), '2/5': (2, 5), '3/10': (3, 10)}

Oder noch etwas mehr “pythonisch”, eleganter:

brueche = [ "1/4", "2/5", "3/10", "1/4" ]

def bruchwert(x):
    zaehler, nenner = [ int(zahlstring) for zahlstring in x.split("/") ]
    return zaehler, nenner

ergebnis = { b: bruchwert(b) for b in brueche }
ergebnis
{'1/4': (1, 4), '2/5': (2, 5), '3/10': (3, 10)}

Statt eine Liste mit 2 Werten zurückzugeben, können wir auch gleich die zwei Werte dividieren.

brueche = [ "1/4", "2/5", "3/10", "1/4" ]

def bruchwert(x):
    zaehler, nenner = [ int(zahlstring) for zahlstring in x.split("/") ]
    return zaehler / nenner

ergebnis = { b: bruchwert(b) for b in brueche }
ergebnis
{'1/4': 0.25, '2/5': 0.4, '3/10': 0.3}

Fertig: So einfach geht das!

Nebenrechnungen#

x = "1/4"
x.split("/")
['1', '4']
x_list = [ int(z) for z in x.split("/")]
x_list
[1, 4]
zaehler, nenner = x_list[0], x_list[1]
zaehler, nenner
(1, 4)

elegant:

zaehler, nenner = x_list
zaehler, nenner
(1, 4)

Klausuraufgabe!#

gegeben: eine List Comprehension, z.B.

meine_liste = ["Hallo", "Welt"]

doppelte = [ 2*z for z in meine_liste ]
doppelte
['HalloHallo', 'WeltWelt']

allgemein:

def meinefunktion(x):
    ...
[ meinefunktion(z) for z in meine_liste ]
[None, None]

gesucht: Dieser Ausdruck konventionell als “Grundstrukur”

def meinefunktion(irgendwas):
    return 2 * irgendwas

doppelte = []
for z in meine_liste:
    # print(z*z)
    doppelte.append(meinefunktion(z))
doppelte
['HalloHallo', 'WeltWelt']

das als Dict-Comprehension:

doppelte_dict = { z: meinefunktion(z) for z in meine_liste }
doppelte_dict
{'Hallo': 'HalloHallo', 'Welt': 'WeltWelt'}
doppelte_dict[ meine_liste[0] ]
'HalloHallo'

Aufgabe: Wie sieht die folgende “doppelte” List Comprehension aus, wenn man sie konventionell mit for-Schleifen etc. formuliert?

l = [ p*q for p in [1,2,3] for q in ["a", "b", "c", "d"] ]
l
['a', 'b', 'c', 'd', 'aa', 'bb', 'cc', 'dd', 'aaa', 'bbb', 'ccc', 'ddd']