Zum Inhalt springen

Vektoren in Rust

Ein Vektor (Vec) ist wie ein Array, kann aber zur Laufzeit wachsen und schrumpfen. Brauchst du im Rust-Alltag eine Liste, greifst du viel öfter zu einem Vec als zu einem Array mit fester Größe.

fn main() {
let numbers: Vec<i32> = vec![1, 2, 3];
println!("{:?}", numbers);
}

vec![] ist ein Makro (achte auf das !). Es baut aus einer Liste von Werten einen Vec – ganz ähnlich, wie du ein Array-Literal schreiben würdest.

▶ Selbst ausprobieren

Du kannst auch mit einem leeren Vektor anfangen und ihn nach und nach füllen:

let mut numbers: Vec<i32> = Vec::new();

Mit .push() hängst du ein Element ans Ende an. Weil du den Vektor dabei veränderst, muss er mut sein:

fn main() {
let mut numbers = Vec::new();
numbers.push(1);
numbers.push(2);
numbers.push(3);
println!("{:?}", numbers);
}

Ausgabe:

[1, 2, 3]
▶ Selbst ausprobieren

Das funktioniert mit denselben eckigen Klammern wie bei Arrays:

fn main() {
let fruits = vec!["Apfel", "Banane", "Kirsche"];
println!("{}", fruits[0]);
println!("Länge: {}", fruits.len());
}
▶ Selbst ausprobieren

Sicherer ist .get(): Es löst bei einem ungültigen Index keine Panic aus, sondern gibt dir eine Option zurück (mehr dazu auf der Seite Option):

fn main() {
let fruits = vec!["Apfel", "Banane", "Kirsche"];
match fruits.get(10) {
Some(fruit) => println!("Gefunden: {fruit}"),
None => println!("An diesem Index gibt es kein Obst"),
}
}
▶ Selbst ausprobieren
fn main() {
let mut numbers = vec![1, 2, 3, 4, 5];
numbers.pop(); // entfernt das letzte Element -> [1, 2, 3, 4]
numbers.remove(0); // entfernt per Index -> [2, 3, 4]
println!("{:?}", numbers);
}
▶ Selbst ausprobieren
fn main() {
let numbers = vec![10, 20, 30];
for n in &numbers {
println!("{n}");
}
}
▶ Selbst ausprobieren

Achte auf das & vor numbers. Mit for n in &numbers leihst du dir jedes Element nur aus (Borrowing, Ausleihen), statt die Ownership (Eigentum) am Vektor zu übernehmen. Lässt du das & weg, wird der Vektor in die Schleife verschoben – danach kannst du numbers nicht mehr benutzen. Ausleihen ist fast immer das, was du willst.

Der Typ wird Vec<i32> geschrieben. Der Teil <i32> bedeutet „ein Vektor aus i32-Werten“. Diese Schreibweise mit spitzen Klammern nennt man Generics; ausführlich geht es darum auf der Seite Generics. Für den Moment liest du Vec<T> einfach als „ein Vektor mit Werten vom Typ T“.

Beginne mit einem leeren Vektor. Lauf über die Zahlen von 1 bis 10 und füge nur die geraden mit push hinzu. Gib dann den Vektor aus und wie viele Elemente er hat. Tipp: Eine Zahl n ist gerade, wenn n % 2 == 0 gilt.

Lösung anzeigen
fn main() {
let mut evens = Vec::new();
for n in 1..=10 {
if n % 2 == 0 {
evens.push(n);
}
}
println!("{:?}", evens);
println!("{} gerade Zahlen gefunden", evens.len());
}

Ausgabe:

[2, 4, 6, 8, 10]
5 gerade Zahlen gefunden
▶ Selbst ausprobieren

Fällt dir auf, dass wir den Typ nie hingeschrieben haben? Rust sieht die push(n)-Aufrufe und leitet daraus ab, dass evens ein Vec<i32> ist.

Leg drei Teller auf einen Vektor: "blau", "grün" und dann "rot". Nimm mit .pop() zwei Teller von oben weg und gib jeden aus. Gib zum Schluss aus, was übrig ist. Tipp: .pop() gibt eine Option zurück, also gib sie mit {:?} aus.

Lösung anzeigen
fn main() {
let mut plates = Vec::new();
plates.push("blau");
plates.push("grün");
plates.push("rot");
println!("Genommen: {:?}", plates.pop());
println!("Genommen: {:?}", plates.pop());
println!("Übrig: {:?}", plates);
}

Ausgabe:

Genommen: Some("rot")
Genommen: Some("grün")
Übrig: ["blau"]
▶ Selbst ausprobieren

pop() nimmt immer das letzte Element, das du hinzugefügt hast – wie den obersten Teller von einem Stapel. Es gibt Some(...) zurück und nicht den reinen Wert, weil der Vektor ja leer sein könnte. Dann bekämst du None statt eines Absturzes.

  • Vec<T> ist eine Liste, die wachsen kann. Du erstellst sie mit vec![...] oder Vec::new().
  • .push() hängt ans Ende an, .pop() entfernt das letzte Element, .remove(i) entfernt per Index.
  • vec[i] löst bei einem ungültigen Index eine Panic aus. .get(i) gibt stattdessen eine Option zurück und bleibt ohne Panic.
  • Mit for item in &vec leihst du dir die Elemente aus, statt den Vektor zu verbrauchen.

Kurzer Check

1. Was passiert, wenn du einen Vec mit einem ungültigen Index ansprichst, z. B. numbers[10]?

2. Mit welcher Methode kannst du einen Index abfragen, ohne eine Panic zu riskieren?

3. Was bewirkt das & in for n in &numbers?

Punkte: 0 / 3