Ve

Vektoren in Julia

1 Übung

Über Vektoren

Ein zentrales Ziel von Julia ist es, Berechnungen mit numerischen Daten schnell und effizient durchführen zu können. Mit sehr vielen numerischen Daten.

Typischerweise werden die Daten in Arrays (oder einem verwandten Typ) gespeichert, man kann also mit Recht sagen, dass Arrays das Herzstück der Sprache Julia sind.

Arrays können eine beliebige Größe haben (nur begrenzt durch den Speicher deiner Hardware) und beliebig viele Dimensionen aufweisen.

Einige Array-Typen haben besondere Namen (aus der linearen Algebra übernommen). Ein eindimensionales Array heißt Vector und ein zweidimensionales Array heißt Matrix. Beide sind in Julia Untertypen von Array.

Dieses einführende Konzept konzentriert sich auf die Grundlagen von Vektoren. Höherdimensionale Arrays werden später im Lehrplan behandelt.

Vektoren erstellen

In Julia ist ein Vector eine geordnete Folge von Werten, auf die über eine Indexnummer zugegriffen werden kann.

Der einfachste Weg, einen Vector zu erstellen, ist, die Werte in eckigen Klammern aufzulisten:

julia> num_vec = [1, 4, 9]
3-element Vector{Int64}:
 1
 4
 9

julia> str_vec = ["arrays", "are", "important"]
3-element Vector{String}:
 "arrays"
 "are"
 "important"

Der Typ des Vectors entspricht dem Typ jedes Elements.

Technisch gesehen ist er ein Spaltenvektor, aber ignoriere das bitte vorerst, wenn du dich mit linearer Algebra nicht auskennst. Nach dem Konzept zu mehrdimensionalen Arrays wird das deutlich klarer.

Vektoren müssen also homogen sein (alle Elemente vom selben Typ)?

In gewisser Hinsicht ja, und wenn du die beste Leistung willst, solltest du das anstreben. Julia kann diese Einschränkung jedoch (falls nötig) umgehen, indem es den Typ Any verwendet:

julia> mixed_vector = [1, "str", 'c']
3-element Vector{Any}:
 1
  "str"
  'c': ASCII/Unicode U+0063 (category Ll: Letter, lowercase)

Beim Erstellen eines leeren Vectors verwendet Julia standardmäßig den Elementtyp Any, aber du kannst ihn genauer festlegen, indem du das leere Array mit dem gewünschten Elementtyp annotierst.

julia> empty_vec = []
Any[]

julia> empty_int_vec = Int64[]
Int64[]

Vorbefüllte Vektoren

Es ist sehr verbreitet, mit Vektoren zu beginnen, die nur aus Nullen oder nur aus Einsen bestehen. Dafür gibt es Funktionen namens (wenig überraschend) zeros() und ones(), die die Vektorgröße als Parameter übernehmen. Der Standardtyp ist Float64, aber optional können auch andere numerische Typen angegeben werden.

Analog dazu nimmt die Funktion fill() sowohl einen zu wiederholenden Wert als auch die gewünschte Vektorgröße entgegen.

julia> zeros(3)
3-element Vector{Float64}:
 0.0
 0.0
 0.0

julia> ones(3)
3-element Vector{Float64}:
 1.0
 1.0
 1.0

julia> ones(Int64, 3)
3-element Vector{Int64}:
 1
 1
 1

julia> fill(42, 3)
3-element Vector{Int64}:
 42
 42
 42

Es gibt noch viele weitere Möglichkeiten: siehe das Handbuch.

Bitte lies und merke dir diese Regel:

  • Standardmäßig beginnt die Indizierung in Julia bei 1, nicht bei 0.

Das ist jedem vertraut, der schon einmal andere Data-Science-Sprachen (R, Matlab, Fortran...) verwendet hat, mag aber für Informatiker mit Erfahrung in C-ähnlichen Sprachen schockierend wirken.

Ansonsten funktionieren die Indizes wie du vielleicht erwartest: setze sie einfach in eckige Klammern:

squares = [0, 1, 4, 9, 16]
squares[1]  # 0
squares[3]  # 4
squares[begin]  # 0 ("begin" is synonym for 1)
squares[end]  # 16 ("end" is synonym for length(squares))

Beachte, wie praktisch die Indizierung mit end (sehr nützlich) und begin (wohl eher nicht) ist.

Python-Programmierer fragen sich vielleicht, wie es mit negativen Indizes aussieht. Vergiss es: die gibt es in Julia nicht, und sie lösen einen BoundsError aus, ebenso wie jeder Index kleiner als 1 oder größer als length(squares).

Operationen mit Vektoren

Vektoren in Julia sind veränderbar: wir können den Inhalt einzelner Zellen ändern.

julia> vals = [1, 3, 5, 7]
4-element Vector{Int64}:
 1
 3
 5
 7

julia> vals[2] = 4  # reassign the value of this element
4

# Only the value at position 2 changes:
julia> vals
4-element Vector{Int64}:
 1
 4
 5
 7

Es gibt viele verfügbare Funktionen zum Bearbeiten von Vektoren, allerdings verallgemeinert die Julia-Dokumentation sie zu „Collections“ statt zu Vektoren.

Beachte, dass Funktionen, die ihre Eingabewerte verändern, per Konvention ein ! im Namen tragen. Der Compiler erzwingt das nicht, aber in der Julia-Welt ist es eine sehr starke Konvention.

Hier sind einige der nützlichen Funktionen:

  • Um Werte am Ende des Vektors hinzuzufügen, verwende push!().
  • Um den letzten Wert zu entfernen, verwende pop!().
  • Um am Anfang des Vektors zu arbeiten, sind die entsprechenden Funktionen pushfirst!() und popfirst!().
  • Um ein Element an einer beliebigen Position einzufügen oder zu entfernen, gibt es insert!() und deleteat!().
julia> vals = [1, 3]
2-element Vector{Int64}:
 1
 3

julia> push!(vals, 5, 6)  # can add multiple values
4-element Vector{Int64}:
 1
 3
 5
 6

julia> pop!(vals)  # mutates vals, return popped value
6

julia> vals
3-element Vector{Int64}:
 1
 3
 5

Verkettung

Die Verkettung ist bei Vektoren recht einfach, doch ein Blick ins Handbuch warnt vor den Komplexitäten, die uns bei mehrdimensionalen Arrays erwarten.

Die Funktion append!() kann eine Mischung aus mehreren Vektoren und einzelnen Elementen als Eingabewerte entgegennehmen.

julia> append!([1, 2], [3, 4], [-1, -2], 15)
7-element Vector{Int64}:
  1
  2
  3
  4
 -1
 -2
 15
Über GitHub bearbeiten Der Link öffnet sich in einem neuen Fenster oder Tab

Lerne Vektoren