Mapa
Podstawowe operacje
- Mapę tworzymy za pomocą metody
new
dla typuHashMap
let mut map = HashMap::new();
- Dodawanie i usuwanie elementów do mapy za pomocą metod
insert
iremove
:map.insert(String::from("world"), 1); map.insert(String::from("rust"), 2); map.remove("world");
- Pobieranie wartości za pomocą metody
get
:let cnt : Option<&i32> = map.get("rust"); // returns an optional reference to a value in the map
- Iteracja po elementach mapy (parach klucz-wartość) odbywa się według zasad omówionych przy okazji wektora:
for (text, number) in &map { // immutable borrow println!("{} has {} occurrences", text, number); }
Ćwiczenie - statystyka wyrazów
- Napisz funkcję
words_stat
, która przyjmuje listę wyrazów i zwraca mapę, która posiada statystykę wystąpień poszczególnych wyrazów.fn words_stats(words: &Vec<String>) -> HashMap<String, i32> { todo!(); }
- Sprawdź statystyki utworu Pan Tadeusz z wykorzystaniem następującego kodu:
fn hash_map_words_stats_poem() { let response = reqwest::blocking::get("https://wolnelektury.pl/media/book/txt/pan-tadeusz.txt").expect("Cannot get poem from a given URL"); let poem = response.text().unwrap(); let stats = words_stats(&split_to_words(&poem)); let sorted_stats = sort_stats(&stats); println!("{:?}", &sorted_stats[..20]); } fn split_to_words(s: &str) -> Vec<String> { let mut words = Vec::new(); for word in s.split_whitespace() { let unified_word = word.trim_matches(|c| char::is_ascii_punctuation(&c)).to_lowercase(); words.push(unified_word); } words } fn sort_stats(stats : &HashMap<String, i32>) -> Vec<(&str, i32)> { let mut sorted_stats : Vec<(&str, i32)> = Vec::new(); for (word, count) in stats.iter() { sorted_stats.push((word, *count)); } sorted_stats.sort_by(|(_, c1), (_, c2)| c2.partial_cmp(c1).expect("FAILED")); sorted_stats }
Typ Entry
- Rust definiuje typ Entry, który jest widokiem na elementy w mapie. Reprezentuje on element posiadający wartość (
Occupied
) oraz element pusty (Vacant
):pub enum Entry<'a, K: 'a, V: 'a> { Occupied(OccupiedEntry<'a, K, V>), Vacant(VacantEntry<'a, K, V>), }
- Aby uzyskać widok
Entry
dla danego klucza, wykorzystujemy metodęentry
:let entry = map.entry("rust");
- Typ
Entry
definiuje szereg metod, które pozwalają w przyjazny sposób obsłużyć sytuacje, w których nie jesteśmy pewni czy dana wartość istnieje w mapie czy nie. Przykładem jest tutaj metodaor_insert
, a poniżej jej zastosowanie w funkcji zliczającej wyrazy:let count : &i32 = map.entry(word.to_owned()).or_insert(0); *count += 1;
- Metoda
or_insert
zwraca mutowalną pożyczkę, a więc może być wykorzystana po lewej stronie przypisania, wtedy nasz kod wygląda jeszcze krócej:map.entry(word.to_owned()).or_insert(0) += 1;
- Inna metoda
and_modify
pozwala z wykorzystaniem domknięć (o których będzie za chwilę) zdefiniować przepis na modyfikację elementu, zanim nastąpi ewentualne dodanie nowych wartości. Skutek wykonania poniższego kodu jest taki sam jak w poprzednim przykładzie:map.entry(word.to_owned()).and_modify(|counter| *counter += 1).or_insert(1);
Ćwiczenie
- Zmodyfikuj przykład liczenia wyrazów, tak aby wykorzystać typ
Entry
.