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.
Einen Vektor erstellen
Abschnitt betitelt „Einen Vektor erstellen“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.
Du kannst auch mit einem leeren Vektor anfangen und ihn nach und nach füllen:
let mut numbers: Vec<i32> = Vec::new();Elemente hinzufügen
Abschnitt betitelt „Elemente hinzufügen“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]Auf Elemente zugreifen
Abschnitt betitelt „Auf Elemente zugreifen“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());}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"), }}Elemente entfernen
Abschnitt betitelt „Elemente entfernen“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);}Mit einer Schleife über einen Vektor laufen
Abschnitt betitelt „Mit einer Schleife über einen Vektor laufen“fn main() { let numbers = vec![10, 20, 30];
for n in &numbers { println!("{n}"); }}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.
Kurz zu Generics
Abschnitt betitelt „Kurz zu Generics“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“.
Übungen
Abschnitt betitelt „Übungen“1. Die geraden Zahlen sammeln
Abschnitt betitelt „1. Die geraden Zahlen sammeln“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 gefundenFä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.
2. Ein Tellerstapel
Abschnitt betitelt „2. Ein Tellerstapel“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"]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.
Zusammenfassung
Abschnitt betitelt „Zusammenfassung“Vec<T>ist eine Liste, die wachsen kann. Du erstellst sie mitvec![...]oderVec::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 eineOptionzurück und bleibt ohne Panic.- Mit
for item in &vecleihst du dir die Elemente aus, statt den Vektor zu verbrauchen.
Kurzer Check
Abschnitt betitelt „Kurzer Check“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
Weiterlesen
Abschnitt betitelt „Weiterlesen“- Wertlisten in Vektoren ablegen – Das Rust-Buch: Vektoren erstellen, lesen und ändern – und warum du kein
pushmachen kannst, während du eine Referenz hältst. - Vectors – Rust by Example (auf Englisch): ein ausführbares Beispiel mit den häufigsten
Vec-Operationen. Vec– Doku der Standardbibliothek (auf Englisch): die vollständige Liste der Methoden, etwainsert,retain,extendundcontains.- Das Makro
vec!– Doku der Standardbibliothek (auf Englisch): alle Formen vonvec!, auchvec![0; 10]für wiederholte Werte.