Wörterbücher und Hash-Tabellen in Rust 1.75: Ausführliche Anleitung
Словари и хеш-таблицы в Rust
Что такое словарь и зачем он нужен?
Представь, что у тебя есть список друзей, и ты хочешь быстро найти номер телефона по имени. Если бы ты хранил всё в обычном списке, тебе пришлось бы просматривать каждую запись, пока не найдёшь нужную. Это долго и неудобно.
Словарь (в Rust он называется HashMap) — это как волшебная записная книжка. В ней каждая запись состоит из двух частей: ключа (например, имя друга) и значения (например, номер телефона). Когда ты хочешь найти номер, ты просто говоришь "дай мне номер по имени 'Анна'" — и компьютер мгновенно находит ответ.
Словари очень быстрые, потому что они используют хеш-таблицу. Хеш-таблица — это как супер-умный шкаф с ячейками. Компьютер превращает ключ (например, слово "Россия") в короткий код (хеш) и кладёт значение в ячейку с этим номером. Чтобы найти значение, нужно снова вычислить хеш ключа — и сразу попасть в нужную ячейку!
Основной синтаксис
Чтобы использовать словарь в Rust, сначала нужно его подключить. В начале программы напиши:
use std::collections::HashMap;
Теперь создадим пустой словарь:
let mut spravochnik = HashMap::new();
Добавим в него записи. Ключи и значения могут быть разными типами, но все ключи должны быть одного типа, и все значения — одного типа.
spravochnik.insert(String::from("Анна"), String::from("123-456"));
spravochnik.insert(String::from("Борис"), String::from("789-012"));
Чтобы получить значение по ключу, используем метод get. Он возвращает Option — либо Some(&значение), если ключ есть, либо None, если нет.
match spravochnik.get("Анна") {
Some(nomer) => println!("Номер Анны: {}", nomer),
None => println!("Контакт не найден"),
}
Можно проверить, есть ли ключ в словаре:
if spravochnik.contains_key("Борис") {
println!("Борис есть в справочнике!");
}
Удалить запись:
spravochnik.remove("Борис");
Перебрать все записи:
for (klyuch, znachenie) in &spravochnik {
println!("{}: {}", klyuch, znachenie);
}
Пример: Приветствия для путешественника
Создадим словарик приветствий для разных стран:
use std::collections::HashMap;
use std::io;
fn main() {
let mut privetstviya = HashMap::new();
privetstviya.insert(String::from("Россия"), String::from("Здравствуйте!"));
privetstviya.insert(String::from("Англия"), String::from("Hello!"));
privetstviya.insert(String::from("Франция"), String::from("Bonjour!"));
privetstviya.insert(String::from("Испания"), String::from("¡Hola!"));
println!("Введите название страны:");
let mut strana = String::new();
io::stdin().read_line(&mut strana).expect("Ошибка чтения");
let strana = strana.trim();
match privetstviya.get(strana) {
Some(privet) => println!("В {} говорят: {}", strana, privet),
None => println!("Извините, я не знаю приветствия для этой страны."),
}
}
Пример: Телефонный справочник
Поиск номера телефона по имени:
use std::collections::HashMap;
use std::io;
fn main() {
let mut telefon = HashMap::new();
telefon.insert(String::from("Мария"), String::from("+7-912-345-67-89"));
telefon.insert(String::from("Иван"), String::from("+7-903-456-78-90"));
telefon.insert(String::from("Елена"), String::from("+7-916-567-89-01"));
println!("Введите имя для поиска:");
let mut imya = String::new();
io::stdin().read_line(&mut imya).expect("Ошибка");
let imya = imya.trim();
match telefon.get(imya) {
Some(nomer) => println!("Номер {}: {}", imya, nomer),
None => println!("Абонент '{}' не найден.", imya),
}
}
Пример: Книжная карточка дел на неделю
Добавляем дела для каждого дня:
use std::collections::HashMap;
use std::io;
fn main() {
let mut plan = HashMap::new();
plan.insert(String::from("Понедельник"), String::from("Уборка, зарядка"));
plan.insert(String::from("Вторник"), String::from("Магазин, готовка"));
plan.insert(String::from("Среда"), String::from("Чтение, прогулка"));
println!("Введите день недели:");
let mut den = String::new();
io::stdin().read_line(&mut den).expect("Ошибка");
let den = den.trim();
match plan.get(den) {
Some(dela) => println!("Дела на {}: {}", den, dela),
None => println!("На этот день дел нет."),
}
}
Пример: Удаление контакта из блокнота
use std::collections::HashMap;
use std::io;
fn main() {
let mut bloknot = HashMap::new();
bloknot.insert(String::from("Анна"), String::from("111-111"));
bloknot.insert(String::from("Петр"), String::from("222-222"));
bloknot.insert(String::from("Ольга"), String::from("333-333"));
println!("Какой контакт удалить?");
let mut imya = String::new();
io::stdin().read_line(&mut imya).expect("Ошибка");
let imya = imya.trim();
if bloknot.remove(imya).is_some() {
println!("Контакт '{}' удалён.", imya);
} else {
println!("Контакт '{}' не найден.", imya);
}
println!("Остались контакты:");
for (k, v) in &bloknot {
println!("{}: {}", k, v);
}
}
Пример: Список товаров магазина
use std::collections::HashMap;
fn main() {
let mut tovary = HashMap::new();
tovary.insert(String::from("Хлеб"), 50);
tovary.insert(String::from("Молоко"), 80);
tovary.insert(String::from("Яблоки"), 120);
println!("Список товаров и цены:");
for (tovar, cena) in &tovary {
println!("{}: {} рублей", tovar, cena);
}
}
Частые ошибки новичков
- Забыть подключить HashMap. Всегда пиши
use std::collections::HashMap;в начале. - Использовать строки без
String::from. В Rust строки по умолчанию — это&str, а в словарь нужно кластьString. ПишиString::from("текст"). - Забыть
mut. Если ты хочешь добавлять или удалять записи, словарь должен быть изменяемым:let mut dict = HashMap::new();. - Не обрабатывать
Option. МетодgetвозвращаетOption. Всегда используйmatchилиif let, чтобы проверить, есть ли значение. - Думать, что порядок сохраняется. В
HashMapпорядок записей не определён. Если нужен порядок, используйBTreeMap.
Итоговый пример: Сборник контактов
Объединим всё, что узнали: добавим несколько контактов, найдём один, удалим другой и выведем всё на экран.
use std::collections::HashMap;
use std::io;
fn main() {
let mut kontakty = HashMap::new();
kontakty.insert(String::from("Алиса"), String::from("+1-555-1234"));
kontakty.insert(String::from("Боб"), String::from("+1-555-5678"));
kontakty.insert(String::from("Чарли"), String::from("+1-555-9012"));
println!("Поиск контакта. Введите имя:");
let mut poisk = String::new();
io::stdin().read_line(&mut poisk).expect("Ошибка");
let poisk = poisk.trim();
match kontakty.get(poisk) {
Some(nom) => println!("Найден: {} - {}", poisk, nom),
None => println!("Не найден."),
}
println!("Введите имя для удаления:");
let mut udalit = String::new();
io::stdin().read_line(&mut udalit).expect("Ошибка");
let udalit = udalit.trim();
if kontakty.remove(udalit).is_some() {
println!("Удалён.");
} else {
println!("Такого контакта нет.");
}
println!("Оставшиеся контакты:");
for (imya, telefon) in &kontakty {
println!("{}: {}", imya, telefon);
}
}
Словари — мощный инструмент. Они помогают хранить данные парами "ключ-значение" и быстро их находить. Используй их, когда нужно связать одно с другим: имя с номером, страну с приветствием, день недели с делами. Удачи в программировании!