Im Konzept Vectors haben wir gesagt, dass „Arrays im Herzen der Sprache Julia stehen" und dass ein Vektor eindimensional ist.
Vor diesem Hintergrund dürfen wir wohl hoffen, dass die Sprache viele vielseitige und mächtige Möglichkeiten bietet, mit Vektoren etwas anzustellen, was auch immer das heißen mag.
Einige sehr einfache Funktionen nehmen einen Vektor als Eingabe und geben einen Skalar zurück.
v = [2, 3, 4]
length(v) # => 3
sum(v) # => 9
Angenommen, du hast einen numerischen Vektor und möchtest von jedem Wert 0.5 abziehen.
julia> v = [1.2, 1.5, 1.7]
3-element Vector{Float64}:
1.2
1.5
1.7
julia> v - 0.5
ERROR: MethodError: no method matching -(::Vector{Float64}, ::Float64)
Das schlägt fehl. Wie sieht es also aus, wenn wir einen anderen Vektor abziehen?
julia> v - [0.5, 0.5, 0.5]
3-element Vector{Float64}:
0.7
1.0
1.2
Es funktioniert, aber es ist recht mühsam und speicherhungrig, wenn die Vektoren länger werden.
Zum Glück hat Julia einen „magischen" Punkt, der dieses Problem ganz einfach löst: v .- 0.5 ist alles, was du brauchst.
Der nächste Abschnitt erklärt, warum.
Also: v - 0.5 schlägt fehl, aber v .- 0.5 funktioniert, und wir müssen verstehen, was der Punkt macht.
Zwei Dinge, die zusammen das gewünschte Ergebnis liefern.
Erstens: Setzt man einen Punkt vor einen Infix-Operator, bedeutet das „Wende diese Operation auf jedes Element einzeln an".
Ebenso wird eine Funktion „vektorisiert", wenn man einen Punkt nach einen Funktionsnamen setzt, selbst wenn die Funktion für skalare Eingaben geschrieben wurde.
julia> sqrt.([1, 4, 9])
3-element Vector{Float64}:
1.0
2.0
3.0
In einem früheren Beispiel haben wir gesehen, dass wir Vektoren gleicher Länge subtrahieren können. Bitte beachte aber, dass .- der sicherere Operator ist als -, weil er die elementweise Absicht deutlich macht.
julia> v .- [0.5, 0.5, 0.5]
3-element Vector{Float64}:
0.7
1.0
1.2
Was ist mit Vektoren ungleicher Länge?
julia> v .- [0.5, 0.5]
ERROR: DimensionMismatch: arrays could not be broadcast to a common size
julia> v .- [0.5,]
3-element Vector{Float64}:
0.7
1.0
1.2
Im Allgemeinen sind ungleiche Längen ein Fehler, außer wenn eine Länge 1 hat (technisch gesehen eine „Singleton"-Dimension).
Singletons wie [0.5,] oder einfach 0.5 werden automatisch durch Wiederholung auf die nötige Länge erweitert.
Das ist der Kern von broadcasting.
Das Auswählen von Elementen eines Vektors über die Indexnummer wurde in früheren Konzepten behandelt.
a = collect('A':'Z') # => 26-element Vector{Char}
# index with an integer
a[2] # => 'B'
# index with a range
a[12:2:18] # => ['L', 'N', 'P, 'R']
# index with another vector
a[ [1, 3, 5] ] # => ['A', 'C', 'E']
Es ist auch möglich, Elemente auszuwählen, die einen logischen Ausdruck erfüllen (technisch gesehen ein „Prädikat"). Das erfordert normalerweise Broadcasting.
julia> a[a .< 'D']
3-element Vector{Char}:
'A': ASCII/Unicode U+0041 (category Lu: Letter, uppercase)
'B': ASCII/Unicode U+0042 (category Lu: Letter, uppercase)
'C': ASCII/Unicode U+0043 (category Lu: Letter, uppercase)
Bei komplexeren Ausdrücken wuchern die Punkte leicht (aber sie sind klein und leicht zu tippen).
julia> a[a .< 'D' .|| a .> 'W']
6-element Vector{Char}:
'A': ASCII/Unicode U+0041 (category Lu: Letter, uppercase)
'B': ASCII/Unicode U+0042 (category Lu: Letter, uppercase)
'C': ASCII/Unicode U+0043 (category Lu: Letter, uppercase)
'X': ASCII/Unicode U+0058 (category Lu: Letter, uppercase)
'Y': ASCII/Unicode U+0059 (category Lu: Letter, uppercase)
'Z': ASCII/Unicode U+005A (category Lu: Letter, uppercase)
Zur Erinnerung: Der „Vektor" kann tatsächlich jedes geeignete geordnete iterierbare Objekt sein, zum Beispiel ein Range:
julia> n = 3:10
3:10
julia> n[isodd.(n)]
4-element Vector{Int64}:
3
5
7
9
Du bist ein begeisterter Vogelbeobachter und hältst fest, wie viele Vögel in den letzten sieben Tagen deinen Garten besucht haben.
Du hast sechs Aufgaben, die sich alle mit der Anzahl der Vögel befassen, die deinen Garten besucht haben.
Implementiere die Funktion today(), die zurückgibt, wie viele Vögel heute deinen Garten besucht haben.
Die Vogelzahlen sind nach Tagen geordnet: Das erste Element ist die Anzahl des ältesten Tages, das letzte Element die Anzahl von heute.
julia> birds_per_day = [2, 5, 0, 7, 4, 1]
julia> today(birds_per_day)
1
Implementiere die Funktion increment_todays_count(), die die heutige Anzahl erhöht:
julia> birds_per_day = [2, 5, 0, 7, 4, 1]
julia> increment_todays_count(birds_per_day)
[2, 5, 0, 7, 4, 2]
Implementiere die Funktion has_day_without_birds(), die true zurückgibt, wenn es einen Tag gab, an dem null Vögel den Garten besucht haben; andernfalls gib false zurück:
julia> birds_per_day = [2, 5, 0, 7, 4, 1]
julia> has_day_without_birds(birds_per_day)
true
Implementiere die Funktion count_for_first_days(), die die Anzahl der Vögel zurückgibt, die seit Beginn der Woche deinen Garten besucht haben. Beschränke die Zählung dabei auf die angegebene Anzahl von Tagen ab Beginn der Woche.
julia> birds_per_day = [2, 5, 0, 7, 4, 1]
julia> count_for_first_days(birds_per_day, 4)
14
Manche Tage sind geschäftiger als andere.
Ein geschäftiger Tag ist ein Tag, an dem fünf oder mehr Vögel deinen Garten besucht haben.
Implementiere die Funktion busy_days(), die die Anzahl der geschäftigen Tage zurückgibt:
julia> birds_per_day = [2, 5, 0, 7, 4, 1]
julia> busy_days(birds_per_day)
2
Du beschließt, deine Aufzeichnungen zu erweitern, indem du die Zahlen für mehrere Wochen führst. In jedem Fall sind die Zahlen nach Wochentagen geordnet, vom Montag als erstem Eintrag bis zum Sonntag als letztem.
Implementiere die Funktion average_per_day(), die den Durchschnitt für 2 Wochen zurückgibt.
julia> week1 = [7, 2, 9, 1, 3, 0, 10]
julia> week2 = [2, 6, 4, 1, 3, 8, 9]
julia> average_per_day(week1, week2)
[4.5, 4.0, 6.5, 1.0, 4.0, 3.0, 9.5]
Melde dich bei Exercism an, um Julia mit 35 Konzepte128 Übungen und echtem menschlichen Mentoring zu lernen und zu meistern, alles kostenlos.