Shanraq.org Shanraq.org
Словарь и множество: посчитать метки
IT

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 и одну уникальную метку. Сортировка касается только списка для вывода, исходная статистика не меняется. Это основа будущих сводок органайзера, но сами задачи пока не сохраняются между запусками.

Вспомните без страницы

  1. Почему в множестве нет двух одинаковых меток?
  2. Что означает None от counts.get(tag)?
  3. Зачем сортировать метки перед показом?

Задание

Обязательное. Добавьте в вывод количество задач с меткой «дом»: Дом: 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)

Пока нет комментариев. Будьте первым.