Tracks
/
Python
Python
/
Übungen
/
Mecha-Mampf-Management
Mecha-Mampf-Management

Mecha-Mampf-Management

Lernübung

Einführung

Die Klasse dict in Python bietet viele nützliche Methoden für die Arbeit mit Dictionaries. Einige wurden bereits im Konzept zu dicts vorgestellt. Hier behandeln wir noch ein paar weitere, zusammen mit einigen Techniken zum Durchlaufen und Bearbeiten von Dictionaries.

setdefault() für fehlerfreies Einfügen verwenden

Das Konzept zu Dictionaries hat bereits behandelt, dass .get(key, <default value>) einen vorhandenen value oder den default value zurückgibt, wenn ein key nicht in einem Dictionary gefunden wird, und so einen KeyError vermeidet. Das funktioniert gut in Situationen, in denen du keine zusätzliche Fehlerbehandlung möchtest, aber nicht sicher sein kannst, dass ein gesuchter key vorhanden ist.

Für eine ähnlich „sichere“ Einfügeoperation (ohne KeyError) gibt es die Methode .setdefault(key, <default value>). setdefault(key, <default value>) gibt den value zurück, wenn der key im Dictionary gefunden wird. Wenn der Schlüssel nicht gefunden wird, fügt sie das Paar (key, default value) ein und gibt den default value zur Verwendung zurück.

>>> palette_I = {'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd'}

# Looking for the value associated with key "Rock Brown".
# The key does not exist, so it is added with the default value, and the value is returned.
>>> palette_I.setdefault('Rock Brown', '#694605')
'#694605'

# The (key, default value) pair has now been added to the dictionary.
>>> palette_I
{'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd', 'Rock Brown': '#694605'}

Mit fromkeys() ein Dictionary aus einem Iterable befüllen

Um ein Dictionary schnell mit verschiedenen keys und Standardwerten zu befüllen, durchläuft die Klassenmethode fromkeys(iterable, <default value>) ein Iterable von keys und erstellt ein neues dict. Alle values werden auf den angegebenen default value gesetzt:

>>> new_dict = dict.fromkeys(['Grassy Green', 'Purple Mountains Majesty', 'Misty Mountain Pink'], 'fill in hex color here')

{'Grassy Green': 'fill in hex color here',
 'Purple Mountains Majesty': 'fill in hex color here',
 'Misty Mountain Pink': 'fill in hex color here'}

Mit Views über Einträge in einem Dictionary iterieren

Die Methoden .keys(), .values() und .items() geben iterierbare Views eines Dictionaries zurück.

Mit diesen Views kannst du bequem über Einträge iterieren, ohne sie zu verändern. Views sind außerdem dynamisch: Wenn sich die zugrunde liegenden Dictionary-Daten ändern, spiegelt das zugehörige view object die Änderung wider:

>>> palette_I = {'Grassy Green': '#9bc400',
                 'Purple Mountains Majesty': '#8076a3',
                  'Misty Mountain Pink': '#f9c5bd'}

# Using .keys() returns a list of keys.
>>> palette_I.keys()
dict_keys(['Grassy Green', 'Purple Mountains Majesty', 'Misty Mountain Pink'])

# Using .values() returns a list of values.
>>> palette_I.values()
dict_values(['#9bc400', '#8076a3', '#f9c5bd'])

# Using .items() returns a list of (key, value) tuples.
>>> palette_I.items()
dict_items([('Grassy Green', '#9bc400'), ('Purple Mountains Majesty', '#8076a3'), ('Misty Mountain Pink', '#f9c5bd')])

# Views are dynamic.  Changing values in the dict changes all of the associated views.
>>> palette_I['Purple Mountains Majesty'] = (128, 118, 163)
>>> palette_I['Deep Red'] = '#932432'

>>> palette_I.values()
dict_values(['#9bc400', (128, 118, 163), '#f9c5bd', '#932432'])

>>> palette_I.keys()
dict_keys(['Grassy Green', 'Purple Mountains Majesty', 'Misty Mountain Pink', 'Deep Red'])

>>> palette_I.items()
dict_items([('Grassy Green', '#9bc400'), ('Purple Mountains Majesty', (128, 118, 163)), ('Misty Mountain Pink', '#f9c5bd'), ('Deep Red', '#932432')])

Mehr zu .keys(), .values() und .items()

Ab Python 3.7 behalten dicts die Reihenfolge bei, in der Einträge eingefügt werden. Das ermöglicht eine First-in-First-out-Iteration (FIFO) bei Verwendung von .keys(), .values() oder .items().

Ab Python 3.8 sind Views außerdem umkehrbar. Dadurch können Schlüssel, Werte oder (key, value)-Paare in Last-in-First-out-Reihenfolge (LIFO) durchlaufen werden, indem du reversed(<dict>.keys()), reversed(<dict>.values()) oder reversed(<dict>.items()) verwendest:

>>> palette_II = {'Factory Stone Purple': '#7c677f', 'Green Treeline': '#478559', 'Purple baseline': '#161748'}

# Iterating in insertion order (First in, first out)
>>> for item in palette_II.items():
...     print(item)
...
('Factory Stone Purple', '#7c677f')
('Green Treeline', '#478559')
('Purple baseline', '#161748')


# Iterating in the reverse direction. (Last in, first out)
>>> for item in reversed(palette_II.items()):
...    print (item)
...
('Purple baseline', '#161748')
('Green Treeline', '#478559')
('Factory Stone Purple', '#7c677f')

Ein Dictionary sortieren

Dictionaries haben keine eingebaute Sortiermethode. Du kannst jedoch eine dict-View mit der eingebauten Funktion sorted() zusammen mit dict.items() sortieren. Die sortierte View kannst du dann verwenden, um ein neues Dictionary zu erstellen. Wie bei der Iteration erfolgt die Standardsortierung über die keys des Dictionaries.

# Default ordering for a dictionary is insertion order (First in, first out).
>>> color_palette = {'Grassy Green': '#9bc400', 
                    'Purple Mountains Majesty': '#8076a3', 
                    'Misty Mountain Pink': '#f9c5bd', 
                    'Factory Stone Purple': '#7c677f', 
                    'Green Treeline': '#478559', 
                    'Purple baseline': '#161748'}
 
 
# The default sort order for a dictionary uses the keys.
>>> sorted_palette = dict(sorted(color_palette.items()))
>>> sorted_palette
{'Factory Stone Purple': '#7c677f',
 'Grassy Green': '#9bc400',
 'Green Treeline': '#478559',
 'Misty Mountain Pink': '#f9c5bd',
 'Purple Mountains Majesty': '#8076a3',
 'Purple baseline': '#161748'}

Dictionaries mit .update() zusammenführen

Mit <dict_one>.update(<dict_two>) kannst du zwei Dictionaries zusammenführen. Diese Methode nimmt die (key,value)-Paare von <dict_two> und schreibt sie in <dict_one>:

>>> palette_I = {'Grassy Green': '#9bc400',
                 'Purple Mountains Majesty': '#8076a3',
                  'Misty Mountain Pink': '#f9c5bd'}
>>> palette_II = {'Factory Stone Purple': '#7c677f',
                  'Green Treeline': '#478559',
                  'Purple Baseline': '#161748'}

>>> palette_I.update(palette_II)

# Note that new items from palette_II are added.
>>> palette_I
{'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd', 'Factory Stone Purple': '#7c677f', 'Green Treeline': '#478559', 'Purple Baseline': '#161748'}

Wenn sich Schlüssel in den beiden Dictionaries überschneiden, wird der value in dict_one durch den entsprechenden value aus dict_two überschrieben:

>>> palette_I =   {'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd', 
                   'Factory Stone Purple': '#7c677f', 'Green Treeline': '#478559', 'Purple baseline': '#161748'}
>>> palette_III = {'Grassy Green': (155, 196, 0), 'Purple Mountains Majesty': (128, 118, 163),
                   'Misty Mountain Pink': (249, 197, 189)}
>>> palette_I.update(palette_III)

# Overlapping values in palette_I are replaced with values from palette_III
>>> palette_I
{'Grassy Green': (155, 196, 0),
  'Purple Mountains Majesty': (128, 118, 163), 
  'Misty Mountain Pink': (249, 197, 189), 
  'Factory Stone Purple': '#7c677f', 
  'Green Treeline': '#478559', 'Purple baseline': '#161748'}

Dictionaries mit den Union-Operatoren (| und |=) zusammenführen oder aktualisieren

Python 3.9 führt eine andere Möglichkeit ein, dicts zusammenzuführen: die union-Operatoren. dict_one | dict_two erstellt ein neues Dictionary, das aus den (key, value)-Paaren von dict_one und dict_two besteht. Wenn beide Dictionaries gemeinsame Schlüssel haben, haben die Werte von dict_two Vorrang.

>>> palette_I = {'Grassy Green': '#9bc400', 'Purple Mountains Majesty': '#8076a3', 'Misty Mountain Pink': '#f9c5bd'}
>>> palette_II = {'Factory Stone Purple': '#7c677f', 'Green Treeline': '#478559', 'Purple baseline': '#161748'}
>>> new_dict = palette_I | palette_II
>>> new_dict
...
{'Grassy Green': '#9bc400',
 'Purple Mountains Majesty': '#8076a3',
 'Misty Mountain Pink': '#f9c5bd',
 'Factory Stone Purple': '#7c677f',
 'Green Treeline': '#478559',
 'Purple baseline': '#161748'}

dict_one |= other verhält sich ähnlich wie <dict_one>.update(<other>), aber hier kann other entweder ein dict oder ein Iterable von (key, value)-Paaren sein:

>>> palette_III = {'Grassy Green': (155, 196, 0),
                   'Purple Mountains Majesty': (128, 118, 163),
                   'Misty Mountain Pink': (249, 197, 189)}
>>> new_dict |= palette_III
>>> new_dict
...
{'Grassy Green': (155, 196, 0),
'Purple Mountains Majesty': (128, 118, 163),
'Misty Mountain Pink': (249, 197, 189),
'Factory Stone Purple': '#7c677f',
'Green Treeline': '#478559',
'Purple baseline': '#161748'}

Für eine ausführliche Erklärung von Dictionaries und Methoden für die Arbeit mit ihnen sind das offizielle Tutorial und die offizielle Bibliotheksreferenz hervorragende Ausgangspunkte.

Real Python und Finxter haben ebenfalls sehr ausführliche Artikel zu Python-Dictionaries.

Anleitung

Mecha Munch™, ein Unternehmen für die Automatisierung von Lebensmitteleinkäufen, hat dich gerade eingestellt, um an ihrer Bestell-App zu arbeiten. Dein Team hat die Aufgabe, ein MVP (minimal funktionsfähiges Produkt) zu bauen, das alle grundlegenden Aktivitäten rund um den Einkaufswagen verwaltet, damit Nutzer ihre Lebensmittelbestellungen hinzufügen, entfernen und sortieren können. Zum Glück kümmert sich ein anderes Team um alles rund um Geld und Bezahlvorgang!

1. Artikel zum Einkaufswagen des Nutzers hinzufügen

Das MVP soll es dem Nutzer ermöglichen, Artikel zu seinem Einkaufswagen hinzuzufügen. Das kann ein einzelner Artikel oder mehrere Artikel auf einmal sein. Da es sich um ein MVP handelt, wird die Menge eines Artikels durch Wiederholungen angegeben. Wenn ein Nutzer 2 Oranges hinzufügen möchte, erscheint 'Oranges' zweimal im Eingabe-Iterable. Hat der Nutzer den Artikel bereits im Einkaufswagen, sollte die Menge im Einkaufswagen um 1 erhöht werden. Ist der Artikel neu im Einkaufswagen, sollte er mit der Menge 1 hinzugefügt werden.

Erstelle die Funktion add_item(<current_cart>, <items_to_add>), die ein Einkaufswagen-Dictionary und ein beliebiges listenähnliches Iterable von hinzuzufügenden Artikeln als Argumente entgegennimmt. Sie sollte ein neues bzw. aktualisiertes Einkaufswagen-Dictionary für den Nutzer zurückgeben.

>>> add_item({'Banana': 3, 'Apple': 2, 'Orange': 1},
              ('Apple', 'Apple', 'Orange', 'Apple', 'Banana'))
{'Banana': 4, 'Apple': 5, 'Orange': 2}

>>> add_item({'Banana': 3, 'Apple': 2, 'Orange': 1},
              ['Banana', 'Orange', 'Blueberries', 'Banana'])
{'Banana': 5, 'Apple': 2, 'Orange': 2, 'Blueberries': 1}

2. Artikel aus der Notizen-App des Nutzers einlesen

Hoppla. Sieht so aus, als würde das Produktteam Feature Creep betreiben. Sie wollen dem MVP zusätzliche Funktionalität hinzufügen. Die Anwendung muss jetzt einen Einkaufswagen erstellen, indem sie Artikel aus der Notizen-App eines Nutzers liest. Bequem für die Nutzer, aber etwas mehr Arbeit für das Team.

Erstelle die Funktion read_notes(<notes>), die ein beliebiges listenähnliches Iterable als Argument entgegennehmen kann. Die Funktion sollte die Artikel einlesen und einen Einkaufswagen bzw. ein Dictionary für den Nutzer erstellen. Jeder Artikel sollte mit der Menge 1 hinzugefügt werden. Anschließend sollte der neue Einkaufswagen des Nutzers zurückgegeben werden.

>>> read_notes(('Banana','Apple', 'Orange'))
{'Banana': 1, 'Apple': 1, 'Orange': 1}

>>> read_notes(['Blueberries', 'Pear', 'Orange', 'Banana', 'Apple'])
{'Blueberries' : 1, 'Pear' : 1, 'Orange' : 1, 'Banana' : 1, 'Apple' : 1}

3. Den Bereich „Ideen“ für Rezepte aktualisieren

Die App hat einen Bereich „Ideen“, der mit fertigen Rezepten aus verschiedenen Küchen gefüllt ist. Der Nutzer kann eines dieser Rezepte auswählen und alle seine Zutaten automatisch zum Einkaufswagen hinzufügen lassen. Der Projektmanager hat dich gebeten, eine Möglichkeit zu schaffen, diese „Ideen“-Rezepte zu bearbeiten, weil das Content-Team ständig Zutaten und Mengen ändert.

Erstelle die Funktion update_recipes(<ideas>, <recipe_updates>), die ein „Ideen“-Dictionary und ein Iterable mit Rezept-Updates als Argumente entgegennimmt. Die Funktion sollte das neue bzw. aktualisierte „Ideen“-Dictionary zurückgeben.

>>>update_recipes(
    {'Banana Bread' : {'Banana': 1, 'Apple': 1, 'Walnuts': 1, 'Flour': 1, 'Eggs': 2, 'Butter': 1},
     'Raspberry Pie' : {'Raspberry': 1, 'Orange': 1, 'Pie Crust': 1, 'Cream Custard': 1}},
    (('Banana Bread', {'Banana': 4,  'Walnuts': 2, 'Flour': 1, 'Butter': 1, 'Milk': 2, 'Eggs': 3}),)
    )
...

{'Banana Bread': {'Banana': 4, 'Walnuts': 2, 'Flour': 1, 'Butter': 1, 'Milk': 2, 'Eggs': 3}, 
 'Raspberry Pie': {'Raspberry': 1, 'Orange': 1, 'Pie Crust': 1, 'Cream Custard': 1}}

>>> update_recipes(
    {'Banana Bread' : {'Banana': 1, 'Apple': 1, 'Walnuts': 1, 'Flour': 1, 'Eggs': 2, 'Butter': 1},
    'Raspberry Pie' : {'Raspberry': 1, 'Orange': 1, 'Pie Crust': 1, 'Cream Custard': 1},
    'Pasta Primavera': {'Eggs': 1, 'Carrots': 1, 'Spinach': 2, 'Tomatoes': 3, 'Parmesan': 2, 'Milk': 1, 'Onion': 1}},
    [('Raspberry Pie', {'Raspberry': 3, 'Orange': 1, 'Pie Crust': 1, 'Cream Custard': 1, 'Whipped Cream': 2}),
    ('Pasta Primavera', {'Eggs': 1, 'Mixed Veggies': 2, 'Parmesan': 2, 'Milk': 1, 'Spinach': 1, 'Bread Crumbs': 1}),
    ('Blueberry Crumble', {'Blueberries': 2, 'Whipped Creme': 2, 'Granola Topping': 2, 'Yogurt': 3})]
    )
...

{'Banana Bread': {'Banana': 1, 'Apple': 1, 'Walnuts': 1, 'Flour': 1, 'Eggs': 2, 'Butter': 1}, 
 'Raspberry Pie': {'Raspberry': 3, 'Orange': 1, 'Pie Crust': 1, 'Cream Custard': 1, 'Whipped Cream': 2}, 
 'Pasta Primavera': {'Eggs': 1, 'Mixed Veggies': 2, 'Parmesan': 2, 'Milk': 1, 'Spinach': 1, 'Bread Crumbs': 1},
 'Blueberry Crumble': {'Blueberries': 2, 'Whipped Creme': 2, 'Granola Topping': 2, 'Yogurt': 3}}

4. Die Artikel im Einkaufswagen sortieren

Sobald ein Nutzer einen Einkaufswagen begonnen hat, erlaubt ihm die App, seine Artikel alphabetisch zu sortieren. Das macht es einfacher, Dinge zu finden, und hilft bei Dateneingabefehlern wie 'potatoes' und 'Potato' in der Datenbank.

Erstelle die Funktion sort_entries(<cart>), die einen Einkaufswagen bzw. ein Dictionary als Argument entgegennimmt und einen neuen, alphabetisch sortierten zurückgibt.

>>> sort_entries({'Banana': 3, 'Apple': 2, 'Orange': 1})
{'Apple': 2, 'Banana':3, 'Orange': 1}

5. Den Einkaufswagen des Nutzers zur Abwicklung an das Geschäft senden

Die App muss den Einkaufswagen eines Nutzers zur Abwicklung an das Geschäft senden. Die Mitarbeiter im Geschäft müssen aber wissen, in welchem Gang des Geschäfts der Artikel zu finden ist und ob er gekühlt werden muss. Deshalb (ziemlich willkürlich) muss der „Abwicklungs-Einkaufswagen“ in umgekehrter alphabetischer Reihenfolge sortiert werden, wobei Artikelmengen mit Standort- und Kühlinformationen kombiniert werden.

Erstelle die Funktion send_to_store(<cart>, <aisle_mapping>), die einen Einkaufswagen und ein Dictionary entgegennimmt, das für jeden Artikel die Gangnummer im Geschäft und ein True/False für die nötige Kühlung enthält. Die Funktion sollte einen kombinierten „Abwicklungs-Einkaufswagen“ zurückgeben (return), der für jeden Artikel, den der Kunde bestellt, Menge, Gang und Kühlung enthält. Die Artikel sollten in umgekehrter alphabetischer Reihenfolge erscheinen.

>>> send_to_store({'Banana': 3, 'Apple': 2, 'Orange': 1, 'Milk': 2},
                  {'Banana': ['Aisle 5', False], 'Apple': ['Aisle 4', False], 'Orange': ['Aisle 4', False], 'Milk': ['Aisle 2', True]})
{'Orange': [1, 'Aisle 4', False], 'Milk': [2, 'Aisle 2', True], 'Banana': [3, 'Aisle 5', False], 'Apple': [2, 'Aisle 4', False]}

6. Den Bestand des Geschäfts an die Bestellung eines Nutzers anpassen.

Die App kann nicht einfach endlos Kundenbestellungen aufgeben. Irgendwann gehen dem Geschäft verschiedene Produkte aus. Also muss dein MVP den Bestand des Geschäfts immer dann aktualisieren, wenn ein Nutzer seine Bestellung an das Geschäft sendet. Sonst bestellen Kunden Produkte, die gar nicht verfügbar sind.

Erstelle die Funktion update_store_inventory(<fulfillment_cart>, <store_inventory>), die einen „Abwicklungs-Einkaufswagen“ und einen Geschäftsbestand entgegennimmt. Die Funktion sollte die Bestandsmengen des Geschäfts um die im „Abwicklungs-Einkaufswagen“ bestellte Anzahl verringern und dann den aktualisierten Bestand zurückgeben. Wenn der Bestand eines Artikels auf 0 fällt, sollte die Anzahl durch die Meldung 'Out of Stock' ersetzt werden.

>>> update_store_inventory({'Orange': [1, 'Aisle 4', False], 'Milk': [2, 'Aisle 2', True], 'Banana': [3, 'Aisle 5', False], 'Apple': [2, 'Aisle 4', False]},
{'Banana': [15, 'Aisle 5', False], 'Apple': [12, 'Aisle 4', False], 'Orange': [1, 'Aisle 4', False], 'Milk': [4, 'Aisle 2', True]})

{'Banana': [12, 'Aisle 5', False], 'Apple': [10, 'Aisle 4', False], 'Orange': ['Out of Stock', 'Aisle 4', False], 'Milk': [2, 'Aisle 2', True]}
Über GitHub bearbeiten Der Link öffnet sich in einem neuen Fenster oder Tab
Python Exercism

Bereit, mit Mecha-Mampf-Management zu starten?

Melde dich bei Exercism an, um Python mit 17 Konzepte146 Übungen und echtem menschlichen Mentoring zu lernen und zu meistern, alles kostenlos.