# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# #  3.4 Lists
#
# ## 3.4.6-3.4.7  Verschachtelte Listen  splitten & Listen verbinden
#
# Im Anschluss dieser Übungseinheit kannst du ...
# + tiefe Listen splitten, auch mehrfach verschachtelte
# + neue Listen aus Teilen bestehender Listen erstellen
# + mehrere Listen miteinander zu neuen Listen verbinden

# ## 3.4.6 Verschachtelte Listen & verschachteltes Slicing
#
# Die Synonyme für verschachtelte Listen sind dir bereits geläufig: nested/tiefe Listen und Lists in Lists - Listen in Listen.  
#
# Sie eignen sich gut dafür, eine Liste hierarchisch zu gliedern. Die Superliste bildet die oberste Ebene, pro Subliste geht es dann eine Stufe in der Hierarchie nach unten.  
#
# Die Listeneinträge der obersten Ebene, der Superliste, können auch nur aus Sublisten bestehen. Die Superliste ist dann der übergeordnete Container der Sublisten. Beispiel mit Städten und Einwohnerzahlen in Millionen:

cities_population = [['Delhi', 27.28], ['Peking', 21.25], ['Tokio', 38.05]]

# Diese Sublisten wären als Dictionarys sogar noch besser geeignet, da sie klare Schlüssel-Werte-Paare bilden.  
#
# Ein paar verschachtelte/nested Lists hast du auch in der vorhergehenden Einheit gesehen. ``.append()`` und ``.insert()`` bilden Sublisten, wenn sie eine Liste mit mindestens einem Eintrag übergeben bekommen. Erinnerung:

# +
lst = [2,4,6,8]

lst.append([10])

print(lst)

# +
lst = [2,4,6,8]

lst.insert(4, [10])

print(lst)
# -

# Eine Liste kann aus beliebig vielen, in sich verschachtelten Listen sowie anderen verschachtelten Datenstrukturen bestehen.  
#
# Beispiel zu einer Liste mit zwei Sublisten:

lst1 = [0, 1, [2,4,6,8], [3,5,9], 10]

# (Die mal gesetzten und in den Sublisten weggelassenen Leerzeichen nach den Kommas sollen dir nur für eine bessere Lesbarkeit behilflich sein.)
#
# Beispiel zu einer Liste mit zwei doppelt verschachtelten Sublisten:

lst2 = [0, 1, [2,4,6,8, [-2, -4, -8]], [3,5,9, [-3, -5, -9]], 10]

# Beispiel zu einer Liste bestehend aus Tupeln. Die Tuples enthalten Namen, Alter und Führerscheinklasse. <b>employees</b> bedeutet "Angestellte":

employees = [('<NAME>', 36, 'A'), ('<NAME>', 28, 'B' ), ('<NAME>', 44, 'C')]

# ### Verschachtelte Listen slicen
#
# Das Slicing verschachtelter Listen funktioniert ganz ähnlich zu dem Slicing flacher Listen.  
# Der Unterschied ist, dass die Sublisten bzw. allgemein die Substrukturen über zwei zusätzliche eckige Klammern angewählt werden.  
#
# Syntax zum Anwählen des zweiten Levels einer Liste: <font color = green>lst[Index][Index]</font>  
# Über die ersten eckigen Klammern werden - wie gewohnt - die Werte der Superliste angewählt. Über die zweiten eckigen Klammern werden die Werte der Substruktur angewählt.  
#
# Je mehr Substrukturen eine Liste hat, desto mehr eckige Klammern müssen zum Anwählen derer Werte hinzugefügt werden.  
#
# **Abbildung zum Zugriff auf Werte in Substrukturen einer Liste:**  
#
# <img src="3-4-5-NestedList.jpg"> 
# <br>
# <br>
#

# <div class="alert alert-block alert-warning">
#     <font size="3"><b>Hinweis zur Bearbeitung dieser Einheit:</b></font>  
# <br>
#     
# Du wirst im Laufe dieser Einheit immer wieder Fragen sowie kleine Aufgaben lesen. Du erkennst sie gleich an ihrer Farbgebung in orange. Überlege dir erst eine Antwort und probier sie aus, bevor du zu der weiter darunterliegenden Code-Zelle scrollst und die Beantwortung liest. Die Antwort ist stets mit einem grünen Block markiert.  
#
# **Wichtige Empfehlung: Auch, wenn das nun doppelt gesagt wird, probier dich bitte erst selbst an einer möglichen Lösung aus, bevor du dir die Auflösung ansiehst.**  
#
# **Wie alle praktischen Tätigkeiten kannst du Programmieren nur durch Übung lernen. Selbst, wenn du nicht auf die Lösung kommen solltest, allein das aktive Nachdenken über sie und das Eintippen von Wegen wird dich zu einem/r besseren ProgrammierIn machen ;-)**
# </div>
#
# ### 3.4.6 a) Eine Liste mit einer Verschachtelung slicen  
#
# Schau dir diese Liste an:

lst1 = [0, 1, [2,4,6,8], [3,5,9], 10]

# <font color = #f57c00>**Zuerst: Wie kommen wir an die erste Subliste mit den Werten [2,4,6,8] ran? Probier es in der folgenden Code-Zelle aus, bevor du weiter scrollst.**</font>
# <br>
# <br>
# <br>
#



# <div class="alert alert-block alert-success">
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br> 
# <b>Antwort:</b>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# </div>

lst1[2]

# Die Subliste liegt auf der gleichen Ebene wie die übrigen Werte der Liste. Sie ist also über [&nbsp;] anwählbar.  
# <br>
# <font color = #f57c00>**Wie gelangen wir an den Wert 8 aus der Subliste?**</font>  
# <br>
# <br>
#

# +
lst1 = [0, 1, [2,4,6,8], [3,5,9], 10]


# -

# <div class="alert alert-block alert-success">
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br> 
# <b>Antwort:</b>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# </div>

lst1[2][3]

# Zuerst wird die Subliste auf dem Index 2 der Superliste angewählt. Dann wird Index 3 innerhalb der Subliste angewählt.  
# <br>
# <font color = #f57c00>**Gib die 5 aus der zweiten Subliste von "lst1" aus.**</font>  
# <br>
# <br>
#

# +
lst1 = [0, 1, [2,4,6,8], [3,5,9], 10]


# -

# <div class="alert alert-block alert-success">
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br> 
# <b>Antwort:</b>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# </div>

lst1[3][1]

# Die zweite Subliste liegt auf Index 3 der Superliste. Die 5 liegt auf Index 1 der Subliste.  
# <br>
# <font color = #f57c00>**Wie alt ist <NAME>? Gib sein Alter aus.**</font>  
# <br>
# <br>
#

# +
employees = [('<NAME>', 36, 'A'), ('<NAME>', 28, 'B' ), ('<NAME>', 44, 'C')]


# -

# <div class="alert alert-block alert-success">
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br> 
# <b>Antwort:</b>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# </div>

employees[2][1]

# Das Tuple zu <NAME> liegt auf Index 2 der Superliste, sein Alter auf deren Index 1.  
#
# **Wie sieht das aus, wenn wir Sequenzen, also Teilabschnitte von Unterlisten ausgeben möchten?**
#
# Beginnen wir mit einem Beispiel, das du  schon kennst.  
# <br>
# <font color = #f57c00>**Wie gibst du die 0 und 1 der Superliste gleichzeitig aus?**</font>  
# <br>
# <br>

# +
lst1 = [0, 1, [2,4,6,8], [3,5,9], 10]


# -

# <div class="alert alert-block alert-success">
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br> 
# <b>Antwort:</b>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# </div>

lst1[0:2]

# Das ist das Slicing, das du schon kennst. Ab dem Index vor dem Doppelpunkt werden alle Werte abgebildet - bis exlusive des Indizes nach dem Doppelpunkt.  
# Das funktioniert ebenso mit Sublisten, nur, dass du zu den "rein" eckigen Klammern **[&nbsp;]** zur Anwahl der Liste bzw. Subliste(n) noch weitere eckige Klammern **[&nbsp;:&nbsp;]** für das Slicing brauchst.  
#   
# <br>
# <font color = #f57c00><b>Gib die 4,6,8 der ersten Subliste aus.</b></font>  
# <br>
# <br>

# +
lst1 = [0, 1, [2,4,6,8], [3,5,9], 10]


# -

# <div class="alert alert-block alert-success">
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br> 
# <b>Antwort:</b>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# </div>

lst1[2][1:4]

# Zuerst wird die Subliste auf Index 2 angewählt. Eine Ebene tiefer slicen wir die Subliste so, dass die Werte ihrer Indize 0-3 abgebildet werden.  
#
# Funktioniert das auch mit negativen Indizes?  
#
# Probier es gleich aus!  
# <br>
# <font color = #f57c00><b>Lass die 3,5 in der Ausgabe erscheinen, indem du nur negative Indize verwendest.</b></font>  
# <br>
# <br>

# +
lst1 = [0, 1, [2,4,6,8], [3,5,9], 10]


# -

# <div class="alert alert-block alert-success">
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br> 
# <b>Antwort:</b>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# </div>

lst1[-2][-3:-1]

# Zur Erinnerung:  
#
# ###  Indextabelle zu List
#
# | Index | ['Wert 1', |'Wert 2', | 'Wert 3',  | 'Wert 4'] 
# |---|---|---|---|---|
# | positiv | 0 | 1 | 2 | 3|
# | negativ| -4 | -3 | -2 | -1|  
#
# Die zweite Subliste liegt auf dem negativen Index -2 der Superliste. Die geforderten Werte liegen in der Subliste auf den Indizen -3 bis inklusive -2. Da ein Index nach dem Doppelpunkt nicht mitzählt, wurde -1 angegeben, um den Wert auf Index -2 abzubilden.  
#
# Praktisch ist die Verwendung negativer Indize bei sehr langen Listen. Wenn man an Werte herankommen möchte, die weiter am Ende liegen, muss nicht die ganze Liste bis zu ihnen hin durchiteriert (= durchlaufen) werden.  
# <br>
# <font color = #f57c00><b>Gib Alter und Führerscheinklasse von Raphaella Racer über negative Indexierung aus.</b></font>  
# <br>
# <br>
#

# +
employees = [('<NAME>', 36, 'A'), ('<NAME>', 28, 'B' ), ('<NAME>', 44, 'C')]


# -

# <div class="alert alert-block alert-success">
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br> 
# <b>Antwort:</b>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  

employees[-2][-2:]

# Weil die Subliste, wie jede Liste, an Index -1 endet, ist die Angabe eines Indizes nach dem Doppelpunkt nicht erforderlich. Denn ohne Angabe eines Indizes nach dem Doppelpunkt wird die jeweilige (Sub-)Liste sowieso bis zu ihrem Ende durchlaufen.    
# <br>
# <br>
#
# ### 3.4.6 b) Eine Liste mit zwei Verschachtelungen slicen  
#
# Die Liste zu den Angestellten wurde in eine Arbeiterliste geändert. Sie besteht nun nur aus Sublisten, von denen die auf zweitem Level verschachtelten Sublisten die Löhne von Januar, Februar und März enthalten:

workers = [['<NAME>', 36, 'A',[1800.0, 2200.0, 1600.0]],\
             ['<NAME>', 28, 'B',[1900.0, 1500.0,2300.0] ],\
             ['<NAME>', 44, 'C', [1700.0, 2100.0, 200.0]]]

# <font color = #f57c00><b>Wie viel hat <NAME> in diesen drei Monaten verdient? Gib die entsprechende Subliste aus.</b></font>  
# <br>
# <br>
#



# <div class="alert alert-block alert-success">
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br> 
# <b>Antwort:</b>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# </div>

workers[0][3]

# Die Subliste zu <NAME> liegt auf Index 0. In dieser Subliste liegt die Lohnliste auf Index 3.  
# <br>
# <font color = #f57c00><b>Wie viel hat <NAME> in diesen drei Monaten verdient? Gib die entsprechende Subliste aus.</b></font>  
# Für alle Mini-Aufgaben gilt: Ob du negative oder positive Indize verwendest, spielt hier keine Rolle, solange du auf das richtige Ergebnis kommst.  
# <br>
# <br>
#

# +
workers = [['<NAME>', 36, 'A',[1800.0, 2200.0, 1600.0]],\
             ['<NAME>', 28, 'B',[1900.0, 1500.0,2300.0] ],\
             ['<NAME>', 44, 'C', [1700.0, 2100.0, 200.0]]]


# -

# <div class="alert alert-block alert-success">
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br> 
# <b>Antwort:</b>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# </div>

workers[-1][-1]

# Oder:

workers[2][3]

# Wenn du weißt, dass ein Wert ganz hinten in der Liste ist, kannst ihn leicht mit **-1** erreichen.  
#
# Nun wollen wir an die Werte der innersten Sublisten ran!
#
# <br>
# <font color = #f57c00><b>Wie viel hat <NAME> im Februar verdient?</b></font>   
# <br>
# <br>
#

# +
employees = [['<NAME>', 36, 'A',[1800.0, 2200.0, 1600.0]],\
             ['<NAME>', 28, 'B',[1900.0, 1500.0,2300.0] ],\
             ['<NAME>', 44, 'C', [1700.0, 2100.0, 200.0]]]


# -

# <div class="alert alert-block alert-success">
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br> 
# <b>Antwort:</b>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# </div>

workers[1][3][1]

# <NAME> liegt auf Index 1, Ihre Löhne in der Subliste auf Index 3, der von Februar in der Sub-Subliste auf Index 1.  
#
# <br>
# <font color = #f57c00><b>Wie viel <NAME> im Januar und Februar verdient?</b></font>   
# <br>
# <br>
#

# +
workers = [['<NAME>', 36, 'A',[1800.0, 2200.0, 1600.0]],\
             ['<NAME>', 28, 'B',[1900.0, 1500.0,2300.0] ],\
             ['<NAME>', 44, 'C', [1700.0, 2100.0, 200.0]]]


# -

# <div class="alert alert-block alert-success">
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br> 
# <b>Antwort:</b>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# </div>

workers[-1][3][0:2]

# <NAME> Subliste liegt auf Index 2 bzw. -1, die Subliste zu seinen Löhnen auf Index 3 bzw. -1, dort liegen sein Januar- und Februarlohn auf Index 0 bis Index 1. Um Index 1 abzubilden, muss nach dem Doppelpunkt Index 2 angegeben werden.  
# <br>
# <font color = #f57c00><b>Wie viel <NAME> im Februar und März verdient?</b></font>   
# <br>
# <br>
#

# +
workers = [['<NAME>', 36, 'A',[1800.0, 2200.0, 1600.0]],\
             ['<NAME>', 28, 'B',[1900.0, 1500.0,2300.0] ],\
             ['<NAME>', 44, 'C', [1700.0, 2100.0, 200.0]]]


# -

# <div class="alert alert-block alert-success">
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br> 
# <b>Antwort:</b>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# </div>

workers[0][3][1:]

# Auch hier musste der Index nach dem Doppelpunkt für den Zugriff auf die Lohnliste nicht angegeben werden, da die Werte bis zum Listenende gefragt waren.  
# <br>
# <br>
#
# ### 3.4.6 c) Eine Liste mit mehr als zwei Verschachtelungen slicen   
#
# Die Arbeiterliste wurde um eine weitere Subliste verschachtelt. Diese Subliste enthält die angesammelten Überstunden der Monate Januar bis März, die früher oder später verrechnet werden sollen.  
#
# In der Praxis wird eine zu tiefe Verschachtelung vermieden. Für gewöhnlich haben Listen kaum mehr als höchstens 4 Verschachtelungsstufen.  
#
# Wenn du die letzten Fragen zu diesem Thema beantworten kannst, bist du richtig fit im Slicen verschachtelter Listen!  
#
# Man nennt das auch "<b>Subsetting von Listen</b>", weil dabei Sublisten extrahiert werden.  
# <br>
# <font color = #f57c00><b>Wie viele Überstunden hat <NAME> von Januar bis März angesammelt? Gib die entsprechende Subliste aus.</b></font>   
# <br>
# <br>
#

# +
workers = [['<NAME>', 36, 'A',[1800.0, 2200.0, 1600.0, [10, 12, 5]]],\
             ['<NAME>', 28, 'B',[1900.0, 1500.0,2300.0, [8, 3, 11]] ],\
             ['<NAME>', 44, 'C', [1700.0, 2100.0, 200.0, [14, 7, 2]]]]


# -

# <div class="alert alert-block alert-success">
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br> 
# <b>Antwort:</b>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# </div>

workers[-1][-1][-1]

# Oder:

workers[2][3][3]

# Toms Liste liegt auf Index -1 bzw. 2 der Superliste. Die Lohnliste liegt dort auf Index -1 bzw. Index 3. Dort liegt die Überstundenliste auf Index -1 bzw. Index 3.  
# <br>
# <font color = #f57c00><b>Wie viele Überstunden hat <NAME> im März angehäuft?</b></font>   
# <br>
# <br>
#

# +
workers = [['<NAME>', 36, 'A',[1800.0, 2200.0, 1600.0, [10, 12, 5]]],\
             ['<NAME>', 28, 'B',[1900.0, 1500.0,2300.0, [8, 3, 11]] ],\
             ['<NAME>', 44, 'C', [1700.0, 2100.0, 200.0, [14, 7, 2]]]]


# -

# <div class="alert alert-block alert-success">
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br> 
# <b>Antwort:</b>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# </div>

workers[1][3][3][-1]

# Die Lohnliste wird mit <b>[1][3]</b> (oder **[-2][-1]**) angewählt. Die Überstundenliste ist dann auf <b>[3]</b> (oder **[-1])** in der Lohnliste. Dort liegen die März-Überstunden auf <b>[2]</b> bzw. <b>[-1]</b>.  
# <br>
# <font color = #f57c00><b>Wie viele Überstunden hat <NAME> im Januar und Februar geleistet?</b></font>   
# <br>
# <br>
#

# +
workers = [['<NAME>', 36, 'A',[1800.0, 2200.0, 1600.0, [10, 12, 5]]],\
             ['<NAME>', 28, 'B',[1900.0, 1500.0,2300.0, [8, 3, 11]] ],\
             ['<NAME>', 44, 'C', [1700.0, 2100.0, 200.0, [14, 7, 2]]]]


# -

# <div class="alert alert-block alert-success">
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br> 
# <b>Antwort:</b>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# </div>

workers[0][3][3][:2]

# Von <NAME>s Subliste wird die Lohnliste auf Index 3 angewählt, danach die Überstundenliste auf Index 3. Da die gefragten Überstunden vom Anfang an bis vor Index 2 laufen, muss vor dem Doppelpunkt kein Index angegeben werden.  
#
# Zu guter Letzt:  
# <br>
# <br>
# <font color = #f57c00><b>Wie viele Überstunden hat <NAME> im Januar und Februar geleistet?</b></font>   
# <br>
# <br>
#

# +
workers = [['<NAME>', 36, 'A',[1800.0, 2200.0, 1600.0, [10, 12, 5]]],\
             ['<NAME>', 28, 'B',[1900.0, 1500.0,2300.0, [8, 3, 11]] ],\
             ['<NAME>', 44, 'C', [1700.0, 2100.0, 200.0, [14, 7, 2]]]]


# -

# <div class="alert alert-block alert-success">
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br> 
# <b>Antwort:</b>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# </div>

workers[-1][-1][-1][:2]

# ### 3.4.6 d) Der Parameter "step"
#
# Für das Slicing aller splittbaren Datentypen ist der Parameter <b>step</b> verfügbar.  
#
# Beispiel zur Ausgabe aller ungeraden Zahlen eines Subsets einer Liste:

# +
lst = [1, 2, 3, 4, 5,[1, 2, 3, 4, 5, 6, 7, 8, 9], 6, 7, 8, 9]

lst[5][::2]
# -

# Die erste Subliste an Index 5 wurde angewählt. Danach wurden mit <b>[&nbsp;:&nbsp;]</b> all ihre Werte ausgewählt. Anschließend wurde mit dem Parameter step [&nbsp;:&nbsp;:**2**] jeder 2. ihrer Werte aufgerufen.  
# <br>
# <br>
#
# ### 3.4.6 e) Eine neue Liste aus einem Subset erstellen
#
# Das Subset einer Liste ist ein extrahierter Teil dieser Liste. Jede Splittung über [&nbsp;:&nbsp;] ergibt ein Subset einer Liste.  
#
# Aus diesen Subsets können neue Listen erstellt werden.  
#
# <font color = red>Das folgende Beispiel zeigt, worauf man achten muss!</font>
#
# In diesem Beispiel besteht die tiefe Liste aus Sublisten zu Städten und Einwohnerzahlen in Millionen:

# +
cities_population = [['Delhi', 27.28], ['Peking', 21.25], ['Tokio', 38.05]]

cities_pop_subset = cities_population[0:2]

print(cities_pop_subset)
# -

# Aus den ersten beiden Listeneinträgen wurde eine neue Liste erstellt.  
#
# Ist das Subset unabhängig vom Original? Was passiert, wenn ein Eintrag im Subset geändert wird? Hat dies Auswirkungen auf das Original?

# +
cities_pop_subset[1][0] = 'Testtown'

print(f'cities_population: {cities_population}')
print(f'cities_pop_subset: {cities_pop_subset}')
# -

# Die gesplittete Liste wurde mit <b>=</b> der neuen Variable <b>cities_pop_subset</b> zugewiesen. Deshalb ist **eine flache Kopie** entstanden, weil die Zuweisung einer tiefen Liste mit der Slice-Notation  <b>[&nbsp;:&nbsp;]</b> stattgefunden hat.  
#
# Die Subliste der Kopie liegt auf der gleichen Speicheradresse wie die Subliste des Originals, denn ihre Werte wurden nicht kopiert:

cities_population[1] is cities_pop_subset[1]

# Mit einer flachen Liste hätte die obere Herangehensweise geklappt. Nicht aber mit einer tiefen Liste.  
#
# Verwenden wir ``copy.deepcopy()`` erhalten wir eine tiefe, unabhängige Kopie der verschachtelten Liste:

# +
import copy

cities_population = [['Delhi', 27.28], ['Peking', 21.25], ['Tokio', 38.05]]

cities_pop_subset = copy.deepcopy(cities_population[0:2])

print(cities_pop_subset)
# -

# Und wir können die Kopie beliebig bearbeiten, ohne das Original zu verändern:

# +
cities_pop_subset[1][0] = 'Testtown'

print(f'cities_population: {cities_population}')
print(f'cities_pop_subset: {cities_pop_subset}')
# -

# Auch ein neuer Eintrag kann somit unabhängig hinzugefügt werden:

# +
cities_pop_subset[2:] = ['Paris', 9.90]

print(f'cities_population: {cities_population}')
print(f'cities_pop_subset: {cities_pop_subset}')
# -

# **Beachte, dass über das Hinzufügen eines neuen Eintrags mittels der Slice-Notation [2:] kein <font color = darkred>IndexError</font> auftritt. Mit der Index-Notation [2] wäre dieser aufgetreten.**
#
#
# ## 3.4.7 Listen verbinden (engl.: concatenating lists)
#
# Du weißt nun, wie man Listen splittet! Doch wie verbindet man sie?  
#
# Die Funktion ``zip()``, mit welcher du mehrere Listen sowie andere Datenstrukturen zu einer neuen Liste (oder anderen Datenstrukturen) zusammenfassen kannst, hast du in Kapitel "3.4.3 Funktionen für List & andere Datentypen" schon kennengelernt.  
#
# Im Folgenden werden dir noch weitere Möglichkeiten zur Verbindung von Listen vorgestellt.  
#
# ### 3.4.7 a) Listen mit "+" verbinden
#
# In diesem Beispiel werden die Einnahmen zweier Quartale verbunden:

# +
revenues01 = [12346.78, 10563,65, 97832.43, 112849.46]
revenues02 = [13128.89, 11494.37, 12436.52, 12973.05]

revenues01_02 = revenues01 + revenues02

print(revenues01_02)
# -

# Auf diese Weise können auch mehr als zwei Listen miteinander verbunden werden.
#
# Die beiden flachen listen wurden mit <b>+</b> zu einer neuen Liste verbunden. Weil die Liste flach ist, ist sie unabhängig von den Originallisten, wie du an der unabhängigen Änderung des ersten Eintrags in der neuen Liste sehen kannst:

# +
revenues01_02[0] = 100000.00

print(revenues01)
print(revenues01_02)
# -

# Vorsicht ist jedoch wieder bei tiefen Listen geboten, wie es in den folgenden beiden Code-Zellen demonstriert wird:

# +
revenues01 = [[12346.78, 13785.21], 10563,65, 97832.43, 112849.46]
revenues02 = [[13128.89], 11494.37, 12436.52, 12973.05]

revenues01_02 = revenues01 + revenues02

print(revenues01_02)

# +
revenues01_02[0][0] = 100000.00

print(revenues01)
print(revenues01_02)
# -

# Auch <b>revenues01</b> wurde verändert.
#
# **Deshalb verwende für das Erstellen von neuen - unabhängigen - Listen aus tiefen Listen ``copy.deepcopy()``!**
#
# <div class="alert alert-block alert-warning">
#     <font size="3"><b>Übung zum Verbinden tiefer Listen:</b></font> Verbinde die Listen so, dass Einträge in ihnen unabhängig voneinander bearbeitet werden können.  
#     
# Weil dieses Wissen sehr wichtig ist, ist die Lösung zu dieser Übung weiter unten abgebildet. Scrolle also nicht nach unten, sondern löse sie zuerst selbst.
# </div>

# +
revenues01 = [[12346.78, 13785.21], 10563,65, 97832.43, 112849.46]
revenues02 = [[13128.89], 11494.37, 12436.52, 12973.05]

revenues01_02 = revenues01 + revenues02

print(revenues01_02)
# -

# <div class="alert alert-block alert-warning">
#     <font size="3"><b>Teste die Unabhängigkeit beider Listen aus:</b></font>
# </div>

# +
revenues01_02[0][0] = 100000.00

print(revenues01)
print(revenues01_02)
# -

# <div class="alert alert-block alert-success">
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br> 
# <b>Antwort:</b>  
# <br>  
# <br>  
# <br>  
# <br>  
# <br>  
# </div>

# +
import copy

revenues01 = [[12346.78, 13785.21], 10563,65, 97832.43, 112849.46]
revenues02 = [[13128.89], 11494.37, 12436.52, 12973.05]

revenues01_02 = copy.deepcopy(revenues01 + revenues02)

print(revenues01_02)

# +
revenues01_02[0][0] = 100000.00

print(revenues01)
print(revenues01_02)
# -

# Die weiteren Herangehensweisen zum Verbinden von Listen werden nun nur noch an flachen Listen demonstriert.  
#
# Behalte dir im Kopf, dass du für tiefe Listen stets ``copy.deepcopy()`` verwenden musst, um eine unabhängige neue Liste zu erhalten.  
# <br>
# <br>
#
# ### 3.4.7 b) Listen mit "*" verbinden
#
# Der Vollständigkeit halber siehst du an diesem Beispiel, wie mit <b>*</b> Listen verbunden werden können:

# +
revenues01 = [12346.78, 10563,65, 97832.43, 112849.46]
revenues02 = [13128.89, 11494.37, 12436.52, 12973.05]

revenues01_02 = [*revenues01, *revenues02]

print(revenues01_02)
# -

# Die Syntax dafür ist etwas umständlicher, weshalb nichts dagegen spricht, Listen einfach mit <b>+</b> zu verbinden.  
#
# Auch auf diese Weise können mehr als zwei Listen miteinander verbunden werden.  
# <br>
# <br>
#
# ### 3.4.7 c) Listen mit .extend() verbinden
#
# Auch über ``.extend()`` können Listen verbunden werden.
#
# Wie wird die über ``.extend()`` erstellte Liste aussehen? Überlege zuerst vor der Ausführung der Code-Zelle.

# +
revenues01 = [12346.78, 10563,65, 97832.43, 112849.46]
revenues02 = [13128.89, 11494.37, 12436.52, 12973.05]

revenues01_02 = revenues01.extend(revenues02)

print(revenues01_02)
# -

# Das kann umgangen werden, indem du der neuen Variable zuerst eine leere Liste zuweist:

# +
revenues01 = [12346.78, 10563,65, 97832.43, 112849.46]
revenues02 = [13128.89, 11494.37, 12436.52, 12973.05]

revenues01_02 = []

revenues01_02.extend(revenues01 + revenues02)

print(revenues01_02)
# -

# Dadurch, dass eine leere Liste auf dem Speicherplatz angelegt und ``.extend()`` auf dessen Variable angewendet wurde, wurde nicht der Speicherplatz von <b>revenues01</b> überschrieben. Stattdessen wurden die Werte in die leere Liste übertragen. 
#
# **Aber diese Tatsache bleibt bestehen: Die neue Liste ist nur unabhängig von den Originallisten, weil diese flach sind.**  
#
# Du kannst die erste Liste, je nach Anforderungen, auch in-place mit der zweiten Liste erweitern:

# +
revenues01 = [12346.78, 10563,65, 97832.43, 112849.46]
revenues02 = [13128.89, 11494.37, 12436.52, 12973.05]

revenues01.extend(revenues02)

print(revenues01)
# -

# ### 3.4.7 d) Mit list() Listen aus anderen Datenstrukturen erstellen und verbinden
#
# Möchtest du andere Datenstrukturen in Listen umwandeln und verbinden, kann du das mit und innerhalb von ``list()``.  
#
# Weil Sets und Dictionarys andere Mechanismen haben, um verbunden zu werden, siehst du hier ein Beispiel mit Tuples.  
#
# Umwandlung zweier Tuple in eine Liste:

# +
revenues01 = (12346.78, 10563,65, 97832.43, 112849.46)
revenues02 = (13128.89, 11494.37, 12436.52, 12973.05)

revenues01_02 = list(revenues01 + revenues02)

print(revenues01_02)
# -

# Tuples sind unveränderlich. Wertänderungen wirken sich deshalb grundsätzlich  niemals auf Tuples aus. In diesem Fall würde eine Wertänderung in der Liste das Tuple auch nicht berühren, weil es anderen Datentyps als List ist.  
#
# <div class="alert alert-block alert-info">
# <font size="3"><b>Tipp:</b></font> Führst du die gleiche Code-Zelle mehrmals hintereinander aus, wird der Code in ihr immer wieder ausgeführt. Genauer gesagt, wenn du eine Funktion auf eine Variable anwendest, wird die Variable immer wieder entsprechend der Funktion verändert.  
#     
# Wenn du zum Beispiel ``.append()`` immer wieder auf eine Liste anwendest, die nicht in der gleichen Code-Zelle gespeichert ist, wird der übergebene Wert in ``.append()`` immer wieder angehängt. Führst du die Code-Zelle drei Mal aus, wird der Wert dann 3 Mal angehängt sein.  
#
# Um das rückgängig zu machen, führe die Code-Zelle, in welcher die ursprüngliche Liste gespeichert ist, erneut aus.  
#
# Alternativ kannst du die Liste auch in der gleichen Code-Zelle speichern, in welcher du die Funktion auf sie anwendest.
# </div>  
# <br>
#
# <div class="alert alert-block alert-warning">
#     <font size="3"><b>Abschließende Übung zum Slicen und Verbinden von Listen:</b></font>  
# <br>
#     
# In dieser Übung erstellst du deine eigene tiefe Liste zu deinen Arbeitern und ihren Löhnen.  
#
# **a)** Du hast die Namen deiner Arbeiter als String vorliegen. Wandle ihn so um, dass jeder Name zu einem <b>Eintrag in einer Liste</b> konvertiert wird.  
# *Hinweis: Weil du noch nicht gelernt hast, wie du aus jedem Namen eine Subliste erstellen kannst, wird diese Liste nicht so verschachtelt sein wie die "workers"-Liste aus 3.4.5. Das Ergebnis von Aufgabe b) wird deshalb auch anders verschachtelt sein.*
#
# **b)** Die <b>Löhne</b> (= <b>wages</b>) deiner Arbeiter von <b>Januar</b> bis <b>März</b> hast du als einzelne Listen vorliegen. Füge sie jeweils <b>nach dem zugehörigen Arbeiter</b> in die Arbeiterliste ein. Gib die Arbeiterliste anschließend aus.  
#
# **c)** Wie viel hat <b><NAME></b> im <b>Januar</b> verdient? Gib den Wert über Slicing aus.
#
# **d)** Erstelle eine neue Liste aus <b>Farshid Fahrers Einnahmen</b> von <b>Januar</b> und <b>Februar</b>. Speichere sie in einer Variable ab und gib die neue Liste aus.  
#
# **e)** Aufgrund eines Fehlers muss der <b>Februar-Lohn</b> von <b>Farshid Fahrer</b> in <b>1745.63</b> in der Liste aus **d)** geändert werden. Gib die geänderte Liste von Farshid Fahrers Einnahmen im Januar und Februar sowie die komplette Arbeiterliste aus. Die Originalliste darf nicht verändert worden sein.  
#
# **f)** In welchem Monat hat <b><NAME> am meisten</b> verdient? Wende die entsprechende Funktion auf den entsprechenden Listeneintrag an. Der höchste Lohn soll in der Ausgabe erscheinen. 
#
# **g)** In welchem Monat hat <b><NAME> am wenigsten</b> verdient? Wende die entsprechende Funktion auf den entsprechenden Listeneintrag an. Der niedrigste Lohn soll in der Ausgabe erscheinen.  
#
# Mit welchen Herangehensweisen du diese Aufgaben löst, ist nicht wichtig, solange du auf die richtigen Ergebnisse kommst und sie nicht der Aufgabenstellung widersprechen.
# </div>

# +
# a)

workers_string = '<NAME>, <NAME>, <NAME>, <NAME>'



# +
# b)

bäcker_wage = [1557.46, 1397.79, 1789.31]
fahrer_wage = [1638.24, 1622.76, 1537.48]
finanzen_wage = [2300.26, 2218.54, 2195.27]
lieferantin_wage = [1743.54, 1529.03, 1658.27]



# +
# c)



# +
# d)



# +
# e)



# +
# f)



# +
# g)


# -

# <div class="alert alert-block alert-success">
# <b>Prima!</b> Verschachteltes Slicen ist dir nun vertraut, ebenso die Erstellung von Listen aus Subsets und mehreren Listen.  
#     
# Solltest du Schwierigkeiten mit der letzten Übung gehabt haben, geh noch einmal die Beispiele in diesem Kapitel durch. Schau dir eventuell in der vorhergehenden Einheit den Abschnitt zu flachen und tiefen Kopien an und in den anderen Einheiten, was es für Funktionen zu Listen gibt.  
# <br>
#     
# In der nächsten Einheit gibt es noch ein paar abschließende Aufgaben zum Kapitel Lists für dich zu lösen.  
# </div>

# <div class="alert alert-block alert-info">
# <h3>Das kannst du aus dieser Übung mitnehmen:</h3>
#
# * **Verschachtelte Listen & verschachteltes Slicing**
#     * verschachtelte Listen werden auch tiefe Listen, nested Lists, Lists in Lists und Listen in Listen genannt
#     * pro Verschachtelungslevel wird ein eckiges Klammernpaar mehr zum Splitten eingesetzt
#     * das Slicing funktioniert wie gewohnt mit: <font color = green>lst[ab hier:bis vor diesen Index:step]</font>
#         * Beispiele:
#             * ``nums = [0, [0, 1, [0, 1, 2], 3, 4], 2, 3]``
#             * Ausgabe von **[[0, 1, [0, 1, 2], 3, 4], 2]** der Superliste: ``nums[1:3]``
#             * Ausgabe der **0** aus der ersten Subliste: ``nums[1][0]``
#             * Ausgabe der **2** aus der zweiten Subliste: ``nums[1][2][2]``
#             * Ausgabe der **3** aus der ersten Subliste: ``nums[1][3]``
#             * Ausgabe der **[0, 1]** aus der zweiten Subliste: ``nums[1][2][:2]``
#             * Ausgabe der **[3, 4]** aus der ersten Subliste: ``nums[1][-2:]``
#             * Ausgabe der **[0, 2]** aus der Superliste (Ausgabe in Zweierschritten): ``nums[::2]``
#             * Rückwärtsausgabe der zweiten Subliste (**[2, 1, 0]**): ``nums[1][2][::-1]``            
# <br>
# * **Neue Listen aus Subsets erstellen**
#     * Subsets sind immer das Ergebnis des Splittens mit <b>[&nbsp;:&nbsp;]</b>
#     * eine flache Liste, die flach bleibt, kann über <b>=</b> aus einer gesplitteten Liste erstellt werden, z.B.: ``subset_lst = flat_lst[1:4]``
#     * bei tiefen Listen erhält man nur ein vom Original unabhängiges Subset, wenn das Subset tief kopiert wird
#         * Beispiel:
#             * zuvor: ``import copy``
#             * z.B.: ``subset_lst = copy.deepcopy(deep_list[1:4])``  
# <br>
# * **Listen verbinden**
#     * heißt in der englischen Literatur <b>concatenating lists</b>
#     * mit ``+``, z.B.: ``new_lst = lst1 + lst2``
#         * Verbindung von mehr als 2 Lists möglich, z.B.: ``new_lst = lst1 + lst2 + lst3 + lst4``
#     * generell wird bei der Verbindung von tiefen Listen für eine tiefe Kopie über das Modul <b>copy</b> die Funktion ``copy.deepcopy()`` angewendet
#         * Beispiel: ``new_lst = copy.deepcopy(lst1 + lst2)``
#     * mit ``*``, z.B.: ``new_lst = [*lst1, *lst2]``
#         * Verbindung von mehr als 2 Lists möglich, z.B.: ``new_lst = [*lst1, *lst2, *lst3, *lst4]``
#     * mit ``.extend()``
#         * Beispiel 1 - lst1 <b>in-place</b> erweitern bzw. mit lst2 verbinden:
#             * ``lst1.extend(lst2)``
#         * Beispiel 2 - die verbundenen flachen Listen <b>auf einer anderen Adresse</b> speichern:
#             * ``lst1_2 = []``
#             * ``lst1_2 = lst1_2.extend(lst1 + lst2)``
#     * mit ``.list()`` Erstellung einer Liste aus <b>anderen Datenstrukturen</b>, z.B. Tupeln: ``new_lst = list(tuple1 + tuple2)``
#     * ``zip()`` zur Vereinigung mehrerer Listen (oder anderen Datenstrukturen) zu einer neuen
#         * Syntax: <font color = green>zip(\*iterables)</font> => beliebig viele (\*) Iterables werden mit einem Komma in den Funktionsklammern getrennt
#         * die Einträge der vereinten Ergebnisliste bestehen aus Tupeln, die jeweils die ersten, dann die zweiten, dritten usw. Listeneinträge der einzelnen Listen vereinen
#         * für die Umwandlung aus dem durch ``zip()`` entstandenen Zip-Objekt ist ``list()`` erforderlich
#         * Beispiel:
#             * ``lst1 = ['A', 'B', 'C']``
#             * ``lst2 = ['D', 'E', 'F']``
#             * ``lst_combined = list(zip(lst1, lst2))``
#             * Output über ``print(lst_combined)`` => [('A', 'D'), ('B', 'E'), ('C', 'F')]
#         * Unzippe die Tuple aus einer gezippten Liste (innerhalb einer Liste) mit ``list(zip(*tuplelist))``
# </div>

StarcoderdataJupyterScriptsDedupFiltered