Wert in HashMap in Rust aktualisieren: vom Anfänger zum Profi

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Wie man einen Wert in einer mutable HashMap in Rust aktualisiert: vom Anfänger zum Profi

\n\n

Haben Sie jemals die Situation erlebt, in der Sie einen Wert in einer HashMap in Rust aktualisieren mussten, der Compiler Ihren Code aber hartnäckig nicht durchließ? Wenn ja – Sie sind nicht allein. Die Frage "How can I update a value in a mutable HashMap?" auf Stack Overflow hat tausende Aufrufe gesammelt, was bedeutet, dass selbst erfahrene Entwickler manchmal über die Nuancen der Arbeit mit dieser Collection stolpern.

\n\n

In diesem Artikel werden wir alle Möglichkeiten zur Aktualisierung von Werten in einer HashMap in Rust durchgehen: vom grundlegenden insert bis zum fortgeschrittenen entry().and_modify(). Sie erfahren, wie Sie Daten richtig ändern, typische Fehler vermeiden und idiomatischen Code schreiben. Los geht's!

\n\n

Warum ist das Aktualisieren in einer HashMap nicht einfach "nehmen und ändern"?

\n\n

Im Gegensatz zu vielen Sprachen zwingt Rust Sie dazu, explizit mit Ownership und Borrowing zu arbeiten. Wenn Sie einen Wert in einer HashMap aktualisieren möchten, müssen Sie drei Aufgaben lösen:

\n\n
    \n
  • Existenz des Schlüssels prüfen – gibt es bereits einen solchen Wert?
  • \n
  • Wert ändern – wenn der Schlüssel existiert, ihn aktualisieren
  • \n
  • Neuen einfügen – wenn der Schlüssel nicht existiert, ihn hinzufügen
  • \n
\n\n

Klingt einfach? Schauen wir uns den Code an.

\n\n

Methode 1: Klassisches insert (aber mit einem Haken)

\n\n

Der direkteste Weg ist die Verwendung von insert. Es überschreibt den Wert, wenn der Schlüssel existiert, oder fügt ein neues Paar ein, wenn der Schlüssel nicht existiert.

\n\n
use std::collections::HashMap;\n\nlet mut scores = HashMap::new();\nscores.insert(String::from("Alice"), 10);\nscores.insert(String::from("Bob"), 20);\n\n// Aktualisieren des Werts für Alice\nscores.insert(String::from("Alice"), 15);\n\nprintln!("{:?}", scores); // {"Alice": 15, "Bob": 20}
\n\n

Funktioniert es? Ja. Aber es gibt einen Haken: insert gibt Option<V> zurück – den alten Wert, falls vorhanden. Das ist nützlich, wenn Sie den vorherigen Wert behalten möchten. Aber was ist, wenn Sie den Wert basierend auf dem alten aktualisieren müssen? Zum Beispiel, um einen Zähler um 1 zu erhöhen?

\n\n
// Wir möchten den Zähler von Alice um 1 erhöhen\nif let Some(score) = scores.get_mut("Alice") {\n    *score += 1;\n}
\n\n

Das funktioniert, erfordert aber zwei Operationen: Prüfung der Existenz und Änderung. Und wenn der Schlüssel nicht existiert? Dann müssten Sie das Einfügen separat durchführen. Nicht sehr elegant.

\n\n

Methode 2: Entry API – der König der Aktualisierungen

\n\n

Rust hat ein mächtiges Werkzeug – die Entry API. Sie ermöglicht es, in einem einzigen Ausdruck die Existenz eines Schlüssels zu prüfen, einen Wert zu aktualisieren oder einzufügen. Dies ist der idiomatische Weg, um mit HashMap zu arbeiten.

\n\n
use std::collections::HashMap;\n\nlet mut word_count = HashMap::new();\n\n// Wörter in einem Satz zählen\nfor word in "hello world hello Rust".split_whitespace() {\n    let count = word_count.entry(word.to_string()).or_insert(0);\n    *count += 1;\n}\n\nprintln!("{:?}", word_count);\n// {"hello": 2, "world": 1, "Rust": 1}
\n\n

Lassen Sie uns die Magie analysieren:

\n
    \n
  • entry(key) – erstellt einen Eintrag für den Schlüssel
  • \n
  • or_insert(0) – wenn der Schlüssel nicht existiert, wird der Wert 0 eingefügt und eine veränderbare Referenz darauf zurückgegeben
  • \n
  • *count += 1 – dereferenziert die Referenz und erhöht den Wert
  • \n
\n\n

Voilà! Eine Zeile – und wir haben das Problem gelöst. Aber das ist noch nicht alles.

\n\n

Methode 3: and_modify – wenn nur aktualisiert werden soll

\n\n

Was ist, wenn Sie einen Wert nur dann aktualisieren möchten, wenn der Schlüssel existiert, und wenn nicht – nichts tun? Oder einen anderen Wert einfügen? Dafür gibt es and_modify und or_insert in einer Kette.

\n\n
use std::collections::HashMap;\n\nlet mut inventory = HashMap::new();\ninventory.insert("apples".to_string(), 10);\ninventory.insert("bananas".to_string(), 5);\n\n// Anzahl der Äpfel um 1 erhöhen, falls vorhanden\ninventory.entry("apples".to_string())\n    .and_modify(|                

Blogs

Buchempfehlungen