Rust: с нуля до своего органайзера Урок 43 из 50
Словарь и множество: посчитать метки
Урок 43. Получить статистику по меткам без зависимости от порядка хранения.
Текст переведён с помощью ИИ.
Предварительно: кортежи, итераторы, collect. Сохраните предыдущий файл и замените src/main.rs учебным примером. Это пока данные в памяти, не содержимое файла органайзера.
Образ и опорная карта
На складе один журнал сообщает, сколько коробок каждой категории, а другой содержит лишь перечень встретившихся категорий. HashMap<K, V> — словарь «ключ → значение», здесь метка → число. HashSet<T> — множество уникальных значений, здесь меток. Угловые скобки называют типы ключа и значения; эту запись мы уже встречали у Vec<T>. Хеш — вычисляемый из ключа код, помогающий выбрать место хранения, как номер секции на складе. Разные ключи могут попасть в одну секцию; коллекция разбирает такое совпадение сама. Образ не задаёт порядок чтения: обход HashMap и HashSet не гарантирован и может меняться между запусками.
Метка → прочитать прежнее число → увеличить → записать; метка → добавить в множество; вывод → сначала упорядочить. use std::collections::{HashMap, HashSet} делает оба имени доступными в этом файле; фигурные скобки после :: перечисляют имена из одного модуля. get(tag) возвращает Some(&число) или None; *value читает число по ссылке. insert заменяет прежнее значение данного ключа или добавляет новое. Повторный insert в множество не создаёт вторую копию метки. into_iter().collect() переносит метки в Vec<&str>, а sort() делает показ предсказуемым. Это технический порядок сравнения строк, а не алфавитный порядок конкретного языка. Индексирование counts["работа"] здесь безопасно только потому, что пример уже добавил этот ключ; неизвестный ключ вызовет панику. Для пользовательского ввода следует применять get и разбирать None.
Запустите подсчёт
Замените src/main.rs и выполните cargo run. HashMap и HashSet входят в стандартную библиотеку Rust, поэтому новых зависимостей нет. Строки ниже — вывод программы, без сообщений Cargo.
use std::collections::{HashMap, HashSet};
fn main() {
let tags = ["работа", "дом", "работа"];
let mut counts: HashMap<&str, usize> = HashMap::new();
let mut unique: HashSet<&str> = HashSet::new();
for tag in tags {
let old = match counts.get(tag) {
Some(value) => *value,
None => 0,
};
counts.insert(tag, old + 1);
unique.insert(tag);
}
let mut sorted: Vec<&str> = unique.into_iter().collect();
sorted.sort();
println!("Метки: {:?}", sorted);
println!("Работа: {}", counts["работа"]);
}
Метки: ["дом", "работа"]
Работа: 2
Два вхождения метки «работа» дают число 2 и одну уникальную метку. Сортировка касается только списка для вывода, исходная статистика не меняется. Это основа будущих сводок органайзера, но сами задачи пока не сохраняются между запусками.
Вспомните без страницы
- Почему в множестве нет двух одинаковых меток?
- Что означает
Noneотcounts.get(tag)? - Зачем сортировать метки перед показом?
Задание
Обязательное. Добавьте в вывод количество задач с меткой «дом»: Дом: 1. Не полагайтесь на порядок обхода HashMap. Затем добавьте ещё одно «дом» во входной массив и предскажите новое число и состав множества.
Ответы
Показать ответы
Ключ уже добавлен в counts, поэтому после существующего вывода можно обратиться к counts["дом"]. При новой метке от пользователя сначала нужен get.
Эталон после попытки
use std::collections::{HashMap, HashSet};
fn main() {
let tags = ["работа", "дом", "работа"];
let mut counts: HashMap<&str, usize> = HashMap::new();
let mut unique: HashSet<&str> = HashSet::new();
for tag in tags {
let old = match counts.get(tag) {
Some(value) => *value,
None => 0,
};
counts.insert(tag, old + 1);
unique.insert(tag);
}
let mut sorted: Vec<&str> = unique.into_iter().collect();
sorted.sort();
println!("Метки: {:?}", sorted);
println!("Работа: {}", counts["работа"]);
println!("Дом: {}", counts["дом"]);
}
Метки: ["дом", "работа"]
Работа: 2
Дом: 1
После проверки
После второго «дом» счётчик станет 2, а список уникальных меток останется прежним. Официальная глава о HashMap · обзор коллекций. Если collect непонятен, вернитесь к уроку 42.
Если вы нашли ошибку или опечатку в тексте статьи, то сообщите нам об этом
Комментарии (0)
Войдите, чтобы оставить комментарий →
Пока нет комментариев. Будьте первым.