Im Konzept „Pairs and Dicts" ging es um die Grundlagen von Julias Wörterbuchtyp.
Da Dicts ein wichtiger und häufig verwendeter Sammlungstyp sind, gibt es auch viele Funktionen, um sie zu bearbeiten.
Der einfachste Weg, einen Eintrag abzurufen, ist über den Schlüssel (wie in vielen Sprachen).
Wenn du allerdings einen Schlüssel abfragst, den es nicht gibt, führt das zu einem KeyError.
julia> d = Dict(i => ('a':'c')[i] for i in 1:3)
Dict{Int64, Char} with 3 entries:
2 => 'b'
3 => 'c'
1 => 'a'
julia> d[2]
'b': ASCII/Unicode U+0062 (category Ll: Letter, lowercase)
# missing key
julia> d[4]
ERROR: KeyError: key 4 not found
Wir könnten prüfen, ob der Schlüssel vorhanden ist, bevor wir versuchen, ihn abzurufen (etwa mit haskey(d, 4)), aber es kann nützlich sein, einfach einen Standardwert für fehlende Schlüssel zu bekommen.
Dafür gibt es die Funktion get() und ihre mutierende Variante get!().
Sie unterscheiden sich darin, ob ein „fehlender" Schlüssel zum Dict hinzugefügt wird.
julia> get(d, 4, '!')
'!': ASCII/Unicode U+0021 (category Po: Punctuation, other)
# get() leaves Dict unchanged
julia> d
Dict{Int64, Char} with 3 entries:
2 => 'b'
3 => 'c'
1 => 'a'
julia> get!(d, 4, '!')
'!': ASCII/Unicode U+0021 (category Po: Punctuation, other)
# get!() adds new key to Dict
julia> d
Dict{Int64, Char} with 4 entries:
4 => '!'
2 => 'b'
3 => 'c'
1 => 'a'
Im vorherigen Konzept haben wir gesehen, dass delete!() einen Eintrag anhand des Schlüssels entfernt.
Das lässt sich mit dem Abrufen des Werts kombinieren, indem du die Funktion pop!() verwendest.
julia> d
Dict{Int64, Char} with 4 entries:
4 => '!'
2 => 'b'
3 => 'c'
1 => 'a'
# popped value is returned
julia> pop!(d, 3)
'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)
# Dict is shrunk
julia> d
Dict{Int64, Char} with 3 entries:
4 => '!'
2 => 'b'
1 => 'a'
Wenn du über ein Dict iterierst, werden standardmäßig key => value-Paare geliefert.
Auf die Bestandteile greifst du mit der üblichen Bezeichnung .first und .second zu.
# d is from the previous example
julia> [(kv.first, kv.second) for kv in d]
3-element Vector{Tuple{Int64, Char}}:
(4, '!')
(2, 'b')
(1, 'a')
Oft wollen wir nur die Schlüssel oder nur die Werte verwenden, was einfach ist.
julia> [k for k in keys(d)]
3-element Vector{Int64}:
4
2
1
julia> [v for v in values(d)]
3-element Vector{Char}:
'!': ASCII/Unicode U+0021 (category Po: Punctuation, other)
'b': ASCII/Unicode U+0062 (category Ll: Letter, lowercase)
'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase)
Zwei Dicts zu kombinieren kann nützlich sein, aber wir müssen uns darüber im Klaren sein, was wir mit Schlüsseln machen wollen, die in mehr als einer Eingabe vorkommen.
Die Funktionen merge() und merge!() kombinieren eine beliebige Anzahl übergebener Dicts von links nach rechts.
Bei vorhandenen Schlüsseln wird der Wert einfach überschrieben, der rechteste Dict „gewinnt" also.
julia> d3 = Dict("color" => "red", "shape" => "circle")
Dict{String, String} with 2 entries:
"shape" => "circle"
"color" => "red"
julia> d4 = Dict("color" => "blue", "coords" => (3, 2))
Dict{String, Any} with 2 entries:
"color" => "blue"
"coords" => (3, 2)
# color from d3 is lost
julia> merge(d3, d4)
Dict{String, Any} with 3 entries:
"shape" => "circle"
"color" => "blue"
"coords" => (3, 2)
Mit den Funktionen mergewith() und mergewith!() können wir eine Funktion als erstes Argument übergeben, um festzulegen, wie wiederholte Schlüssel zusammengeführt werden sollen.
Die Addition ist ein einfaches Beispiel.
julia> d5 = Dict("color" => "red", "area" => 3)
Dict{String, Any} with 2 entries:
"area" => 3
"color" => "red"
julia> d6 = Dict("shape" => "circle", "area" => 5)
Dict{String, Any} with 2 entries:
"shape" => "circle"
"area" => 5
# area values are added, not overwritten
julia> mergewith(+, d5, d6)
Dict{String, Any} with 3 entries:
"shape" => "circle"
"area" => 8
"color" => "red"
Beachte, dass die mergewith-Funktionen ein gutes Beispiel dafür sind, wie Funktionen höherer Ordnung in Aktion aussehen.
Mecha Munch™, ein Unternehmen für die Automatisierung des Lebensmitteleinkaufs, hat dich gerade eingestellt, um an seiner Bestell-App mitzuarbeiten. Dein Team hat die Aufgabe, ein MVP (Minimum Viable Product) zu bauen, das alle grundlegenden Aktivitäten rund um den Warenkorb abdeckt und es Nutzern ermöglicht, ihre Einkäufe hinzuzufügen, zu entfernen und zu sortieren. Zum Glück kümmert sich ein anderes Team um alle Geld- und Bezahlvorgänge!
Der MVP sollte es dem Nutzer ermöglichen, Artikel zu seinem Warenkorb hinzuzufügen. Das kann ein einzelner Artikel oder mehrere auf einmal sein. Da es sich um einen MVP handelt, wird die Artikelmenge durch Wiederholungen angegeben. Wenn ein Nutzer 2 Oranges hinzufügen möchte, erscheint „Oranges" zweimal im übergebenen Iterable. Wenn der Nutzer den Artikel bereits im Warenkorb hat, sollte die Menge im Warenkorb um 1 erhöht werden. Wenn der Artikel neu im Warenkorb ist, sollte er mit der Menge 1 hinzugefügt werden.
Erstelle die Funktion add_items!(<cart>, <items>), die ein Warenkorb-Wörterbuch und ein Iterable von hinzuzufügenden Artikeln als Argumente entgegennimmt.
Sie sollte das aktualisierte Warenkorb-Wörterbuch für den Nutzer zurückgeben.
julia> additems!(Dict("Banana" => 3, "Apple" => 2, "Orange" => 1),
("Apple", "Apple", "Orange", "Apple", "Banana"))
Dict{String, Int64} with 3 entries:
"Apple" => 5
"Orange" => 2
"Banana" => 4
julia> additems!(Dict("Banana" => 3, "Apple" => 2, "Orange" => 1),
["Banana", "Orange", "Blueberries", "Banana"])
Dict{String, Int64} with 4 entries:
"Blueberries" => 1
"Apple" => 2
"Orange" => 2
"Banana" => 5
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 Zutaten automatisch zu seinem Warenkorb hinzufügen lassen. Die Projektleitung hat dich gebeten, eine Möglichkeit zum Bearbeiten dieser „Ideen"-Rezepte zu schaffen, weil das Content-Team ständig Zutaten und Mengen ändert.
Erstelle die Funktion update_recipes!(<ideas>, <updates>), die ein „Ideen"-Wörterbuch und ein Wörterbuch mit Rezeptänderungen als Argumente entgegennimmt.
Die Funktion sollte das aktualisierte „Ideen"-Wörterbuch zurückgeben.
julia>update_recipes!(
Dict("Banana Bread" => Dict("Banana" => 1, "Apple" => 1, "Walnuts" => 1, "Flour" => 1, "Eggs" => 2, "Butter" => 1),
"Raspberry Pie" => Dict("Raspberry" => 1, "Orange" => 1, "Pie Crust" => 1, "Cream Custard" => 1)),
Dict("Banana Bread" => Dict("Banana" => 4, "Walnuts" => 2, "Flour" => 1, "Butter" => 1, "Milk" => 2, "Eggs" => 3))
)
Dict{String, Dict{String, Int64}} with 2 entries:
"Raspberry Pie" => Dict("Cream Custard"=>1, "Raspberry"=>1, "Orange"=>1, "Pie Crust"=>1)
"Banana Bread" => Dict("Eggs"=>3, "Flour"=>1, "Milk"=>2, "Butter"=>1, "Walnuts"=>2, "Banana"=>4)
julia> update_recipes!(
Dict("Banana Bread" => Dict("Banana" => 1, "Apple" => 1, "Walnuts" => 1, "Flour" => 1, "Eggs" => 2, "Butter" => 1),
"Raspberry Pie" => Dict("Raspberry" => 1, "Orange" => 1, "Pie Crust" => 1, "Cream Custard" => 1),
"Pasta Primavera" => Dict("Eggs" => 1, "Carrots" => 1, "Spinach" => 2, "Tomatoes" => 3, "Parmesan" => 2, "Milk" => 1, "Onion" => 1)),
Dict("Raspberry Pie" => Dict("Raspberry" => 3, "Orange" => 1, "Pie Crust" => 1, "Cream Custard" => 1, "Whipped Cream" => 2),
"Pasta Primavera" => Dict("Eggs" => 1, "Mixed Veggies" => 2, "Parmesan" => 2, "Milk" => 1, "Spinach" => 1, "Bread Crumbs" => 1),
"Blueberry Crumble" => Dict("Blueberries" => 2, "Whipped Creme" => 2, "Granola Topping" => 2, "Yogurt" => 3))
)
Dict{String, Dict{String, Int64}} with 4 entries:
"Raspberry Pie" => Dict("Raspberry"=>3, "Orange"=>1, "Pie Crust"=>1, "Cream Custard"=>1, "Whipped Cream"=>2)
"Pasta Primavera" => Dict("Eggs"=>1, "Mixed Veggies"=>2, "Parmesan"=>2, "Milk"=>1, "Spinach"=>1, "Bread Crumbs"=>1)
"Blueberry Crumble" => Dict("Blueberries"=>2, "Whipped Creme"=>2, "Granola Topping"=>2, "Yogurt"=>3)
"Banana Bread" => Dict("Banana"=>1, "Apple"=>1, "Walnuts"=>1, "Flour"=>1, "Eggs"=>2, "Butter"=>1)
Die App muss den Warenkorb eines bestimmten Nutzers zur Abwicklung an den Laden senden. Die Einkäufer im Laden müssen jedoch wissen, wo der Artikel mithilfe eines eindeutigen Gangcodes zu finden ist. Der „Abwicklungs-Warenkorb" muss nach den Gangcodes der Artikel sortiert werden, damit die Einkäufer effizienter arbeiten können.
Erstelle die Funktion send_to_store(<cart>, <aislecodes>), die einen Warenkorb und ein Wörterbuch mit den Gangnummern des Ladens entgegennimmt.
Die Funktion sollte einen kombinierten „Abwicklungs-Warenkorb" zurückgeben, der für jeden bestellten Artikel ein Paar aislecode => quantity enthält.
Die Artikel sollten in der Reihenfolge ihrer Gangcodes erscheinen.
julia> cart = Dict("Orange" => 1, "Milk" => 2, "Banana" => 3, "Apple" => 2, "Chocolate" => 2);
julia> aislecodes = Dict("Orange" => 2.4, "Milk" => 3.3, "Banana" => 2.6, "Apple" => 2.2, "Chocolate" => 5.7);
julia> send_to_store(cart, aislecodes)
5-element Vector{Pair{Float64, Int64}}:
2.2 => 2
2.4 => 1
2.6 => 3
3.3 => 2
5.7 => 2
Die App kann nicht einfach endlos Kundenbestellungen aufgeben. Irgendwann gehen dem Laden verschiedene Produkte aus. Deshalb muss dein MVP den Ladenbestand jedes Mal aktualisieren, wenn ein Nutzer seine Bestellung an den Laden sendet. Sonst bestellen Kunden Produkte, die gar nicht verfügbar sind.
Erstelle die Funktion update_store_inventory!(<inventory>, <cart>), die einen cart und ein inventory entgegennimmt.
Die Funktion sollte die Bestandsmengen des Ladens um die im „cart" bestellten Mengen verringern und dann ein Wörterbuch mit allen Artikeln zurückgeben, die ausverkauft sind (also 0 erreicht haben).
julia> inventory = Dict("Banana" => 15, "Apple" => 12, "Orange" => 1, "Milk" => 4);
julia> cart = Dict("Orange" => 1, "Milk" => 2, "Banana" => 3, "Apple" => 2);
julia> update_store_inventory!(inventory, cart)
Dict{String, Int64} with 1 entry:
"Orange" => 0
julia> inventory
Dict{String, Int64} with 4 entries:
"Milk" => 2
"Apple" => 10
"Orange" => 0
"Banana" => 12
Über die Aktualisierung des Bestands hinaus kann deine App auch beim Auffüllen helfen. Dein MVP sollte in der Lage sein, eine Mini-Bestellung für alle Artikel vorzubereiten, die nach der Bestellung eines Kunden ausverkauft sind. Das macht es einfacher, eine große Bestellung auszulösen. Außerdem gibt es manchmal zeitlich begrenzte Aktionsartikel, die nicht auf der Bestandsliste stehen. Wenn diese vor Ende des Aktionszeitraums ausverkauft sind, haben sie sich als beliebt erwiesen und können zur Bestandsliste hinzugefügt werden.
Erstelle die Funktion reorder!(<outofstock>, <stock>), die outofstock und stock entgegennimmt.
Das stock-Wörterbuch enthält die Standard-Bestandsartikel und ihre Nachbestellmengen.
Das outofstock-Wörterbuch ist das Ergebnis von update_store_inventory!, nämlich ein Wörterbuch mit Artikeln der Menge null.
Die Mengen in outofstock sollten an die in stock angepasst und zurückgegeben werden.
Außerdem sollten alle Artikel in outofstock, die nicht in stock vorhanden sind, mit der Standardmenge 100 zu stock hinzugefügt werden.
julia> inventory = Dict("Banana" => 15, "Apple" => 12, "Orange" => 1, "Milk" => 4, "Chocolate" => 2);
julia> cart = Dict("Orange" => 1, "Milk" => 2, "Banana" => 3, "Apple" => 2, "Chocolate" => 2);
julia> stock = Dict("Banana" => 150, "Apple" => 120, "Orange" => 120, "Milk" => 45);
julia> outofstock = update_store_inventory!(inventory, cart)
Dict{String, Int64} with 1 entry:
"Orange" => 0
"Chocolate" => 0
julia> reorder!(outofstock, stock)
Dict{String, Int64} with 1 entry:
"Orange" => 120
"Chocolate" => 100
julia> stock
Dict{String, Int64} with 5 entries:
"Milk" => 45
"Apple" => 120
"Chocolate" => 100
"Orange" => 120
"Banana" => 150
Melde dich bei Exercism an, um Julia mit 35 Konzepte128 Übungen und echtem menschlichen Mentoring zu lernen und zu meistern, alles kostenlos.