Использование Map

Полностью освойте структуру данных Map в Топазе. От создания до продвинутого использования, охватывая все операции с Map.

Map — это основная структура данных для хранения пар ключ-значение. Изучите мощные возможности Map в Топазе! 🗝️

🌱 Основные концепции Map

Что такое Map?

Map — это ассоциативный массив, который хранит данные в виде пар ключ-значение. Каждый ключ уникален, и значения можно быстро получить через ключи.

// Основное создание и использование Map
function базовыйПримерMap() {
    // Создание пустого map
    let mut картаБаллов: Map<string, int> = Map::new()
    
    // Вставка значений
    картаБаллов.insert("Алиса", 95)
    картаБаллов.insert("Боб", 87)
    картаБаллов.insert("Чарли", 92)
    
    // Получение значений
    match картаБаллов.get("Алиса") { case Some(баллыАлисы) => print!("Баллы Алисы: {}", баллыАлисы), case None => {} }
    
    // Обновление значений
    картаБаллов.insert("Алиса", 98)  // Перезапись существующего значения
    
    // Итерация по всем парам ключ-значение
    for (имя, баллы) in &картаБаллов {
        print!("{}: {}", имя, баллы)
    }
}

// Создание Map литерала
function примерЛитералаMap() -> Map<string, int> {
    map! {
        "Математика" => 90,
        "Наука" => 85,
        "Английский" => 93,
        "История" => 88
    }
}

// Использование составных типов данных как значений
struct ИнформацияСтудента {
    возраст: int,
    курс: int,
    специальность: string
}

function картаСоставныхДанных() -> Map<string, ИнформацияСтудента> {
    let mut картаСтудентов = Map::new()
    
    картаСтудентов.insert("Иван Иванов", ИнформацияСтудента {
        возраст: 20,
        курс: 2,
        специальность: "Информатика".to_string()
    })
    
    картаСтудентов.insert("Мария Петрова", ИнформацияСтудента {
        возраст: 19,
        курс: 1,
        специальность: "Математика".to_string()
    })
    
    return картаСтудентов
} test {
    // Основной тест Map
    let mut тестоваяКарта: Map<string, int> = Map::new()
    тестоваяКарта.insert("ключ1", 100)
    тестоваяКарта.insert("ключ2", 200)
    
    assert тестоваяКарта.get("ключ1") == Some(&100)
    assert тестоваяКарта.get("ключ3") == None
    assert тестоваяКарта.len() == 2
    
    // Тест литерала Map
    let баллыПредметов = примерЛитералаMap()
    assert баллыПредметов.get("Математика") == Some(&90)
    assert баллыПредметов.len() == 4
    
    // Тест составных данных
    let студенты = картаСоставныхДанных()
    match студенты.get("Иван Иванов") { case Some(иван) => { assert иван.возраст == 20; assert иван.специальность == "Информатика" }, case None => {} }
}

базовыйПримерMap()
let картаПредметов = примерЛитералаMap()
print!("Количество предметов: {}", картаПредметов.len())

let картаСтудентов = картаСоставныхДанных()
for (имя, информация) in &картаСтудентов {
    print!("{}: {} лет, {} курс, специальность {}", имя, информация.возраст, информация.курс, информация.специальность)
}

Основные особенности Map

  1. Уникальные ключи: Каждый ключ должен быть уникальным в карте
  2. Быстрый поиск: O(1) средняя временная сложность для получения значений
  3. Динамический размер: Размер может изменяться во время выполнения
  4. Типобезопасность: Типы ключей и значений определяются во время компиляции

🛠️ Основные операции Map

Создание, вставка и получение

// Различные способы создания Map
function способыСозданияMap() {
    // 1. Создание пустой карты
    let mut пустаяКарта: Map<int, string> = Map::new()
    
    // 2. Создание с заданной емкостью
    let mut картаСЕмкостью: Map<string, int> = Map::with_capacity(100)
    
    // 3. Инициализация со значениями по умолчанию
    let mut картаПоУмолчанию = Map::new()
    картаПоУмолчанию.insert("ключПоУмолчанию", "значениеПоУмолчанию")
    
    // 4. Клонирование из другой карты
    let клонированнаяКарта = картаПоУмолчанию.clone()
    
    print!("Размер пустой карты: {}", пустаяКарта.len())
    print!("Размер клонированной карты: {}", клонированнаяКарта.len())
}

// Вставка и обновление значений
function операцииВставкиЗначений() {
    let mut картаСчетчиков: Map<string, int> = Map::new()
    
    // Вставка новых значений
    картаСчетчиков.insert("яблоко", 5)
    картаСчетчиков.insert("банан", 3)
    
    // Обновление существующих значений
    картаСчетчиков.insert("яблоко", 8)  // Изменение 5 -> 8
    
    // Использование Entry API (более эффективно)
    картаСчетчиков.entry("апельсин").or_insert(0)  // Вставить 0, если ключа нет
    картаСчетчиков.entry("яблоко").and_modify(|значение| *значение += 2)  // Добавить 2 к существующему
    
    // Использование возвращаемого значения insert
    match картаСчетчиков.insert("виноград", 7) { case Some(предыдущееЗначение) => print!("Предыдущее значение винограда: {}", предыдущееЗначение), case None => print!("виноград — новый ключ.") }
    
    for (фрукт, количество) in &картаСчетчиков {
        print!("{}: {} штук", фрукт, количество)
    }
}

// Получение значений и проверка существования
function операцииПолученияЗначений() {
    let картаИнвентаря = map! {
        "Яблоко" => 50,
        "Банан" => 30,
        "Апельсин" => 25,
        "Виноград" => 40
    }
    
    // Получение значения с помощью get
    match картаИнвентаря.get("Яблоко") {
        case Some(количество) => print!("Инвентарь яблок: {} штук", количество),
        case None => print!("Нет яблок в инвентаре")
    }
    
    // Проверка существования ключа с помощью contains_key
    if картаИнвентаря.contains_key("Клубника") {
        print!("Клубника доступна")
    } else {
        print!("Нет клубники в инвентаре")
    }
    
    // Получение изменяемой ссылки с помощью get_mut
    let mut изменяемаяКартаИнвентаря = картаИнвентаря.clone()
    match изменяемаяКартаИнвентаря.get_mut("Банан") { case Some(инвентарьБанана) => { *инвентарьБанана -= 10; print!("Инвентарь бананов после продажи: {} штук", *инвентарьБанана) }, case None => {} }
    
    // Получение со значением по умолчанию
    let инвентарьКиви = изменяемаяКартаИнвентаря.get("Киви").unwrap_or(&0)
    print!("Инвентарь киви: {} штук", инвентарьКиви)
}

// Удаление значений
function операцииУдаленияЗначений() {
    let mut временнаяКарта = map! {
        "временный1" => "значение1",
        "временный2" => "значение2",
        "временный3" => "значение3",
        "сохранить" => "важноеЗначение"
    }
    
    print!("Размер до удаления: {}", временнаяКарта.len())
    
    // Удаление конкретного ключа
    match временнаяКарта.remove("временный1") { case Some(удаленноеЗначение) => print!("Удаленное значение: {}", удаленноеЗначение), case None => {} }
    
    // Условное удаление
    временнаяКарта.retain(|ключ, _| !ключ.starts_with("временный"))
    
    print!("Размер после удаления: {}", временнаяКарта.len())
    print!("Оставшиеся ключи: {:?}", временнаяКарта.keys().collect::<Vec<_>>())
    
    // Удаление всех элементов
    временнаяКарта.clear()
    print!("Размер после очистки всех: {}", временнаяКарта.len())
} test {
    // Тест создания карты
    let mut тестоваяКарта: Map<string, int> = Map::new()
    assert тестоваяКарта.is_empty()
    
    // Тест вставки
    тестоваяКарта.insert("ключ1", 100)
    тестоваяКарта.insert("ключ2", 200)
    assert тестоваяКарта.len() == 2
    
    // Тест получения
    assert тестоваяКарта.get("ключ1") == Some(&100)
    assert тестоваяКарта.contains_key("ключ2")
    assert !тестоваяКарта.contains_key("ключ3")
    
    // Тест обновления
    let предыдущееЗначение = тестоваяКарта.insert("ключ1", 150)
    assert предыдущееЗначение == Some(100)
    assert тестоваяКарта.get("ключ1") == Some(&150)
    
    // Тест удаления
    let удаленноеЗначение = тестоваяКарта.remove("ключ2")
    assert удаленноеЗначение == Some(200)
    assert тестоваяКарта.len() == 1
}

способыСозданияMap()
операцииВставкиЗначений()
операцииПолученияЗначений()
операцииУдаленияЗначений()

Итерация и преобразование

// Методы итерации по Map
function методыИтерацииMap() {
    let картаБаллов = map! {
        "Математика" => 95,
        "Наука" => 88,
        "Английский" => 92,
        "История" => 85
    }
    
    // 1. Итерация по парам ключ-значение
    print!("=== Итерация по парам ключ-значение ===")
    for (предмет, баллы) in &картаБаллов {
        print!("{}: {} баллов", предмет, баллы)
    }
    
    // 2. Итерация только по ключам
    print!("=== Итерация только по ключам ===")
    for предмет in картаБаллов.keys() {
        print!("Предмет: {}", предмет)
    }
    
    // 3. Итерация только по значениям
    print!("=== Итерация только по значениям ===")
    for баллы in картаБаллов.values() {
        print!("Баллы: {} баллов", баллы)
    }
    
    // 4. Итерация по изменяемым значениям (корректировка баллов)
    let mut изменяемаяКартаБаллов = картаБаллов.clone()
    for (_, баллы) in &mut изменяемаяКартаБаллов {
        *баллы += 5  // Добавить 5 баллов ко всем оценкам
    }
    
    print!("=== Скорректированные баллы ===")
    for (предмет, баллы) in &изменяемаяКартаБаллов {
        print!("{}: {} баллов", предмет, баллы)
    }
}

// Преобразование и фильтрация Map
function преобразованиеФильтрацияMap() {
    let исходнаяКарта = map! {
        "яблоко" => 10,
        "банан" => 5,
        "апельсин" => 15,
        "виноград" => 8,
        "киви" => 12
    }
    
    // Преобразование карты в вектор
    let векторКлючЗначение: Vec<(string, int)> = исходнаяКарта.iter()
        .map(|(ключ, значение)| (ключ.clone(), *значение))
        .collect()
    
    print!("Вектор ключ-значение: {:?}", векторКлючЗначение)
    
    // Фильтрация элементов по условию
    let дорогиеФрукты: Map<string, int> = исходнаяКарта.iter()
        .filter(|(_, &цена)| цена >= 10)
        .map(|(ключ, значение)| (ключ.clone(), *значение))
        .collect()
    
    print!("Фрукты >= 10: {:?}", дорогиеФрукты)
    
    // Преобразование значений
    let ценыСоСкидкой: Map<string, int> = исходнаяКарта.iter()
        .map(|(ключ, значение)| (ключ.clone(), значение * 90 / 100))  // 10% скидка
        .collect()
    
    print!("Цены со скидкой: {:?}", ценыСоСкидкой)
    
    // Преобразование ключей
    let картаЗаглавныхКлючей: Map<string, int> = исходнаяКарта.iter()
        .map(|(ключ, значение)| (ключ.to_uppercase(), *значение))
        .collect()
    
    print!("Заглавные ключи: {:?}", картаЗаглавныхКлючей)
}

// Агрегация и статистика Map
function агрегацияСтатистикаMap() {
    let данныеПродаж = map! {
        "Январь" => 120,
        "Февраль" => 135,
        "Март" => 98,
        "Апрель" => 156,
        "Май" => 189,
        "Июнь" => 143
    }
    
    // Общие продажи
    let общиеПродажи: int = данныеПродаж.values().sum()
    print!("Общие продажи: {}", общиеПродажи)
    
    // Средние продажи
    let среднийОбъемПродаж = общиеПродажи as f64 / данныеПродаж.len() as f64
    print!("Средние продажи: {:.2}", среднийОбъемПродаж)
    
    // Максимальные/минимальные продажи
    match данныеПродаж.values().max() { case Some(максимальныеПродажи) => print!("Максимальные продажи: {}", максимальныеПродажи), case None => {} }
    match данныеПродаж.values().min() { case Some(минимальныеПродажи) => print!("Минимальные продажи: {}", минимальныеПродажи), case None => {} }
    
    // Количество по конкретному условию
    let месяцевДостиженияЦели = данныеПродаж.values()
        .filter(|&&продажи| продажи >= 140)
        .count()
    print!("Месяцев достижения цели (140): {}", месяцевДостиженияЦели)
    
    // Поиск месяца с лучшими показателями
    match данныеПродаж.iter().max_by_key(|(_, &продажи)| продажи) { case Some((лучшийМесяц, лучшиеПоказатели)) => print!("Лучшие показатели: {} месяц с {} единицами", лучшийМесяц, лучшиеПоказатели), case None => {} }
} test {
    // Тест итерации
    let тестоваяКарта = map! {
        "A" => 1,
        "B" => 2,
        "C" => 3
    }
    
    let mut ключи = Vec::new()
    for ключ in тестоваяКарта.keys() {
        ключи.push(ключ.clone())
    }
    ключи.sort()
    assert ключи == vec!["A", "B", "C"]
    
    // Тест преобразования
    let удвоеннаяКарта: Map<string, int> = тестоваяКарта.iter()
        .map(|(ключ, значение)| (ключ.clone(), значение * 2))
        .collect()
    
    assert удвоеннаяКарта.get("A") == Some(&2)
    assert удвоеннаяКарта.get("B") == Some(&4)
    
    // Тест фильтрации
    let картаБольшихЗначений: Map<string, int> = тестоваяКарта.iter()
        .filter(|(_, &значение)| значение > 1)
        .map(|(ключ, значение)| (ключ.clone(), *значение))
        .collect()
    
    assert картаБольшихЗначений.len() == 2
    assert !картаБольшихЗначений.contains_key("A")
}

методыИтерацииMap()
преобразованиеФильтрацияMap()
агрегацияСтатистикаMap()

🚀 Продвинутое использование Map

Entry API и эффективные паттерны

// Использование Entry API
function использованиеEntryAPI() {
    let mut картаКоличестваСлов: Map<string, int> = Map::new()
    let текст = "привет мир привет rust мир rust программирование"
    
    // Подсчет слов (используя Entry API)
    for слово in текст.split_whitespace() {
        *картаКоличестваСлов.entry(слово.to_string()).or_insert(0) += 1
    }
    
    print!("=== Количество слов ===")
    for (слово, количество) in &картаКоличестваСлов {
        print!("{}: {} раз", слово, количество)
    }
    
    // Сложные паттерны Entry
    let mut картаГрупп: Map<string, Vec<int>> = Map::new()
    let данные = vec![
        ("ГруппаA", 10), ("ГруппаB", 20), ("ГруппаA", 15), 
        ("ГруппаC", 5), ("ГруппаB", 25), ("ГруппаA", 30)
    ]
    
    for (группа, значение) in данные {
        картаГрупп.entry(группа.to_string())
            .or_insert(Vec::new())
            .push(значение)
    }
    
    print!("=== Групповые данные ===")
    for (группа, значения) in &картаГрупп {
        print!("{}: {:?}", группа, значения)
    }
}

// Вложенная структура карт
function вложеннаяСтруктураКарт() {
    // Студент -> Предмет -> Балл
    let mut журналОценок: Map<string, Map<string, int>> = Map::new()
    
    // Функция ввода оценки
    let mut вводОценки = |студент: &str, предмет: &str, балл: int| {
        журналОценок.entry(студент.to_string())
            .or_insert(Map::new())
            .insert(предмет.to_string(), балл)
    }
    
    // Ввод данных
    вводОценки("Иван Петров", "Математика", 95)
    вводОценки("Иван Петров", "Наука", 88)
    вводОценки("Иван Петров", "Английский", 92)
    вводОценки("Мария Иванова", "Математика", 98)
    вводОценки("Мария Иванова", "Наука", 94)
    вводОценки("Мария Иванова", "Английский", 89)
    
    // Запрос оценок
    for (студент, картаПредметов) in &журналОценок {
        print!("=== Оценки {} ===", студент)
        let mut общийБалл = 0
        let mut количествоПредметов = 0
        
        for (предмет, балл) in картаПредметов {
            print!("  {}: {} баллов", предмет, балл)
            общийБалл += балл
            количествоПредметов += 1
        }
        
        let средний = if количествоПредметов > 0 { общийБалл as f64 / количествоПредметов as f64 } else { 0.0 }
        print!("  Средний: {:.1} баллов", средний)
    }
}

// Слияние и объединение карт
function слияниеОбъединениеКарт() {
    let инвентарьA = map! {
        "Яблоко" => 50,
        "Банан" => 30,
        "Апельсин" => 20
    }
    
    let инвентарьB = map! {
        "Банан" => 25,  // Дублирующий ключ
        "Виноград" => 40,
        "Киви" => 15
    }
    
    // 1. Простое слияние (B имеет приоритет)
    let mut объединенныйИнвентарь = инвентарьA.clone()
    for (фрукт, количество) in инвентарьB.iter() {
        объединенныйИнвентарь.insert(фрукт.clone(), *количество)
    }
    
    print!("=== Простое слияние (приоритет B) ===")
    for (фрукт, количество) in &объединенныйИнвентарь {
        print!("{}: {} штук", фрукт, количество)
    }
    
    // 2. Слияние сумм значений
    let mut суммированныйИнвентарь = инвентарьA.clone()
    for (фрукт, количество) in инвентарьB.iter() {
        *суммированныйИнвентарь.entry(фрукт.clone()).or_insert(0) += количество
    }
    
    print!("=== Слияние сумм значений ===")
    for (фрукт, количество) in &суммированныйИнвентарь {
        print!("{}: {} штук", фрукт, количество)
    }
    
    // 3. Слияние максимальных значений
    let mut максИнвентарь = инвентарьA.clone()
    for (фрукт, количество) in инвентарьB.iter() {
        максИнвентарь.entry(фрукт.clone())
            .and_modify(|существующееКоличество| *существующееКоличество = (*существующееКоличество).max(*количество))
            .or_insert(*количество)
    }
    
    print!("=== Слияние максимальных значений ===")
    for (фрукт, количество) in &максИнвентарь {
        print!("{}: {} штук", фрукт, количество)
    }
} test {
    // Тест Entry API
    let mut счетчик: Map<string, int> = Map::new()
    
    // Вставка нового ключа
    счетчик.entry("новыйКлюч".to_string()).or_insert(1)
    assert счетчик.get("новыйКлюч") == Some(&1)
    
    // Изменение существующего ключа
    *счетчик.entry("новыйКлюч".to_string()).or_insert(0) += 5
    assert счетчик.get("новыйКлюч") == Some(&6)
    
    // Тест вложенной карты
    let mut вложеннаяКарта: Map<string, Map<string, int>> = Map::new()
    вложеннаяКарта.entry("внешнийКлюч".to_string())
        .or_insert(Map::new())
        .insert("внутреннийКлюч".to_string(), 100)
    
    assert вложеннаяКарта.get("внешнийКлюч").unwrap().get("внутреннийКлюч") == Some(&100)
}

использованиеEntryAPI()
вложеннаяСтруктураКарт()
слияниеОбъединениеКарт()

Оптимизация производительности и управление памятью

// Управление емкостью и оптимизация производительности
function оптимизацияПроизводительности() {
    // 1. Установка подходящей начальной емкости
    let mut большаяКарта: Map<int, string> = Map::with_capacity(10000)
    
    print!("Начальная емкость: {}", большаяКарта.capacity())
    
    // Вставка большого количества данных
    for i in 0..5000 {
        большаяКарта.insert(i, format!("значение{}", i))
    }
    
    print!("После вставки - длина: {}, емкость: {}", большаяКарта.len(), большаяКарта.capacity())
    
    // 2. Сокращение ненужной емкости
    большаяКарта.shrink_to_fit()
    print!("После сокращения емкости: {}", большаяКарта.capacity())
    
    // 3. Резервирование места
    большаяКарта.reserve(2000)
    print!("После резервирования емкости: {}", большаяКарта.capacity())
}

// Эффективные типы ключей
function эффективныеТипыКлючей() {
    // Пример сравнения производительности строковых ключей vs целочисленных ключей
    
    // Целочисленные ключи (более эффективные)
    let mut картаЦелочисленныхКлючей: Map<u32, string> = Map::new()
    for i in 0..1000 {
        картаЦелочисленныхКлючей.insert(i, format!("данные{}", i))
    }
    
    // Строковые ключи (более высокая стоимость хеширования)
    let mut картаСтроковыхКлючей: Map<string, string> = Map::new()
    for i in 0..1000 {
        картаСтроковыхКлючей.insert(format!("ключ{}", i), format!("данные{}", i))
    }
    
    print!("Размер карты целочисленных ключей: {}", картаЦелочисленныхКлючей.len())
    print!("Размер карты строковых ключей: {}", картаСтроковыхКлючей.len())
    
    // Небольшие строки хранятся в стеке (эффективно)
    let mut картаФиксированныхСтрок: Map<&'static str, int> = map! {
        "Красный" => 1,
        "Синий" => 2,
        "Зеленый" => 3,
        "Желтый" => 4
    }
    
    print!("Карта фиксированных строк: {:?}", картаФиксированныхСтрок)
}

// Использование пользовательской хеш-функции
use std::collections::hash_map::DefaultHasher
use std::hash::{Hash, Hasher}

struct ПользовательскийКлюч {
    id: u32,
    name: string
}

impl Hash for ПользовательскийКлюч {
    function hash<H: Hasher>(&self, state: &mut H) {
        // Использовать только ID для хеша (игнорировать имя)
        self.id.hash(state)
    }
}

impl PartialEq for ПользовательскийКлюч {
    function eq(&self, other: &Self) -> bool {
        self.id == other.id  // Равенство только по ID
    }
}

impl Eq for ПользовательскийКлюч {}

function примерПользовательскогоХеша() {
    let mut пользовательскаяКарта: Map<ПользовательскийКлюч, string> = Map::new()
    
    let ключ1 = ПользовательскийКлюч { id: 1, name: "первый".to_string() }
    let ключ2 = ПользовательскийКлюч { id: 1, name: "другое_имя".to_string() }  // Тот же ID
    
    пользовательскаяКарта.insert(ключ1, "значение1".to_string())
    
    // ключ2 рассматривается как тот же ключ, что и ключ1, потому что у них одинаковый ID
    match пользовательскаяКарта.get(&ключ2) { case Some(значение) => print!("Значение, полученное с пользовательским ключом: {}", значение), case None => {} }
} test {
    // Тест управления емкостью
    let mut тестоваяКарта: Map<int, string> = Map::with_capacity(5)
    
    assert тестоваяКарта.capacity() >= 5
    assert тестоваяКарта.is_empty()
    
    // Тест автоматического расширения при превышении емкости
    for i in 0..<10 {
        тестоваяКарта.insert(i, format!("значение{}", i))
    }
    
    assert тестоваяКарта.len() == 10
    assert тестоваяКарта.capacity() >= 10
}

оптимизацияПроизводительности()
эффективныеТипыКлючей()
примерПользовательскогоХеша()

🎯 Практические паттерны Map

Кеш и мемоизация

// Простая реализация кеша
struct Кеш<K, V>
where
    K: Hash + Eq + Clone,
    V: Clone
{
    данные: Map<K, V>,
    максимальныйРазмер: usize
}

impl<K, V> Кеш<K, V>
where
    K: Hash + Eq + Clone,
    V: Clone
{
    function new(максимальныйРазмер: usize) -> Self {
        Кеш {
            данные: Map::with_capacity(максимальныйРазмер),
            максимальныйРазмер
        }
    }
    
    function get(&self, ключ: &K) -> Option<&V> {
        self.данные.get(ключ)
    }
    
    function put(&mut self, ключ: K, значение: V) {
        if self.данные.len() >= self.максимальныйРазмер {
            // Простой LRU: удалить первый ключ
            match self.данные.keys().next().cloned() { case Some(первыйКлюч) => { self.данные.remove(&первыйКлюч) }, case None => {} }
        }
        self.данные.insert(ключ, значение)
    }
    
    function contains_key(&self, ключ: &K) -> bool {
        self.данные.contains_key(ключ)
    }
    
    function clear(&mut self) {
        self.данные.clear()
    }
}

// Реализация мемоизации
function примерМемоизации() {
    let mut кешФибоначчи: Map<u32, u64> = Map::new()
    
    function фибоначчи(n: u32, кеш: &mut Map<u32, u64>) -> u64 {
        match кеш.get(&n) { case Some(&результат) => return результат, case None => {} }
        
        let результат = match n {
            case 0 => 0,
            case 1 => 1,
            case _ => фибоначчи(n - 1, кеш) + фибоначчи(n - 2, кеш)
        }
        
        кеш.insert(n, результат)
        результат
    }
    
    // Вычисление последовательности Фибоначчи
    for i in 0..15 {
        let значение = фибоначчи(i, &mut кешФибоначчи)
        print!("F({}) = {}", i, значение)
    }
    
    print!("Размер кеша: {}", кешФибоначчи.len())
}

// Симуляция веб-кеша запросов
function симуляцияВебКеша() {
    let mut кешОтветов: Кеш<string, string> = Кеш::new(5)
    
    function симуляцияВебЗапроса(url: &str, кеш: &mut Кеш<string, string>) -> string {
        match кеш.get(&url.to_string()) { case Some(кешированныйОтвет) => { print!("Попадание в кеш: {}", url); return кешированныйОтвет.clone() }, case None => {} }
        
        // Симуляция фактического запроса (с задержкой)
        print!("Фактический запрос: {}", url)
        let ответ = format!("Данные ответа из {}", url)
        
        кеш.put(url.to_string(), ответ.clone())
        ответ
    }
    
    // Симуляция запросов
    let urls = vec![
        "https://api.example.com/users",
        "https://api.example.com/posts", 
        "https://api.example.com/users",  // Попадание в кеш
        "https://api.example.com/comments",
        "https://api.example.com/posts",  // Попадание в кеш
    ]
    
    for url in urls {
        let ответ = симуляцияВебЗапроса(url, &mut кешОтветов)
        print!("Ответ: {}", ответ)
    }
} test {
    // Тест кеша
    let mut тестовыйКеш: Кеш<string, int> = Кеш::new(3)
    
    тестовыйКеш.put("ключ1".to_string(), 100)
    тестовыйКеш.put("ключ2".to_string(), 200)
    тестовыйКеш.put("ключ3".to_string(), 300)
    
    assert тестовыйКеш.get(&"ключ1".to_string()) == Some(&100)
    assert тестовыйКеш.contains_key(&"ключ2".to_string())
    
    // Тест поведения LRU при превышении емкости
    тестовыйКеш.put("ключ4".to_string(), 400)
    
    // Первый ключ должен быть удален
    assert тестовыйКеш.get(&"ключ4".to_string()) == Some(&400)
}

примерМемоизации()
симуляцияВебКеша()

Индексирование и группировка

// Индексирование данных
struct Пользователь {
    id: u32,
    имя: string,
    возраст: u32,
    отдел: string
}

function индексированиеДанных() {
    let пользователи = vec![
        Пользователь { id: 1, имя: "Иван Петров".to_string(), возраст: 28, отдел: "Разработка".to_string() },
        Пользователь { id: 2, имя: "Мария Иванова".to_string(), возраст: 32, отдел: "Дизайн".to_string() },
        Пользователь { id: 3, имя: "Алексей Сидоров".to_string(), возраст: 25, отдел: "Разработка".to_string() },
        Пользователь { id: 4, имя: "Елена Смирнова".to_string(), возраст: 29, отдел: "Маркетинг".to_string() },
    ]
    
    // Индексирование по ID
    let индексID: Map<u32, &Пользователь> = пользователи.iter()
        .map(|пользователь| (пользователь.id, пользователь))
        .collect()
    
    // Индексирование по имени
    let индексИмен: Map<string, &Пользователь> = пользователи.iter()
        .map(|пользователь| (пользователь.имя.clone(), пользователь))
        .collect()
    
    // Группировка по отделам
    let mut группыОтделов: Map<string, Vec<&Пользователь>> = Map::new()
    for пользователь in &пользователи {
        группыОтделов.entry(пользователь.отдел.clone())
            .or_insert(Vec::new())
            .push(пользователь)
    }
    
    // Примеры использования индексов
    match индексID.get(&2) { case Some(пользователь) => print!("Пользователь с ID 2: {}", пользователь.имя), case None => {} }
    match индексИмен.get("Алексей Сидоров") { case Some(пользователь) => print!("Отдел Алексея Сидорова: {}", пользователь.отдел), case None => {} }
    
    // Вывод результатов группировки
    for (отдел, участники) in &группыОтделов {
        print!("=== {} ===", отдел)
        for пользователь in участники {
            print!("  {} ({} лет)", пользователь.имя, пользователь.возраст)
        }
    }
}

// Система мультииндексирования
struct МультиИндекс<T> {
    данные: Vec<T>
}

impl МультиИндекс<Пользователь> {
    function new(данные: Vec<Пользователь>) -> Self {
        МультиИндекс { данные }
    }
    
    function найтиПоID(&self, id: u32) -> Option<&Пользователь> {
        self.данные.iter().find(|пользователь| пользователь.id == id)
    }
    
    function найтиПоОтделу(&self, отдел: &str) -> Vec<&Пользователь> {
        self.данные.iter()
            .filter(|пользователь| пользователь.отдел == отдел)
            .collect()
    }
    
    function найтиПоДиапазонуВозраста(&self, минВозраст: u32, максВозраст: u32) -> Vec<&Пользователь> {
        self.данные.iter()
            .filter(|пользователь| пользователь.возраст >= минВозраст && пользователь.возраст <= максВозраст)
            .collect()
    }
    
    function статистика(&self) -> Map<string, u32> {
        let mut картаСтатистики = Map::new()
        
        // Количество участников по отделам
        let mut количествоПоОтделам: Map<string, u32> = Map::new()
        for пользователь in &self.данные {
            *количествоПоОтделам.entry(пользователь.отдел.clone()).or_insert(0) += 1
        }
        
        // Средний возраст
        let общийВозраст: u32 = self.данные.iter().map(|пользователь| пользователь.возраст).sum()
        let среднийВозраст = if !self.данные.is_empty() { 
            общийВозраст / self.данные.len() as u32 
        } else { 0 }
        
        картаСтатистики.insert("общееКоличествоУчастников".to_string(), self.данные.len() as u32)
        картаСтатистики.insert("среднийВозраст".to_string(), среднийВозраст)
        
        for (отдел, количество) in количествоПоОтделам {
            картаСтатистики.insert(format!("{}_участники", отдел), количество)
        }
        
        картаСтатистики
    }
}

function примерМультиИндекса() {
    let данныеПользователей = vec![
        Пользователь { id: 1, имя: "Иван Петров".to_string(), возраст: 28, отдел: "Разработка".to_string() },
        Пользователь { id: 2, имя: "Мария Иванова".to_string(), возраст: 32, отдел: "Дизайн".to_string() },
        Пользователь { id: 3, имя: "Алексей Сидоров".to_string(), возраст: 25, отдел: "Разработка".to_string() },
        Пользователь { id: 4, имя: "Елена Смирнова".to_string(), возраст: 29, отдел: "Маркетинг".to_string() },
    ]
    
    let индекс = МультиИндекс::new(данныеПользователей)
    
    // Различные поиски
    match индекс.найтиПоID(3) { case Some(пользователь) => print!("ID 3: {}", пользователь.имя), case None => {} }
    
    let участникиРазработки = индекс.найтиПоОтделу("Разработка")
    print!("Участники разработки: {:?}", участникиРазработки.iter().map(|u| &u.имя).collect::<Vec<_>>())
    
    let молодыеСотрудники = индекс.найтиПоДиапазонуВозраста(25, 30)
    print!("25-30 лет: {:?}", молодыеСотрудники.iter().map(|u| &u.имя).collect::<Vec<_>>())
    
    // Вывод статистики
    let статистика = индекс.статистика()
    for (элемент, значение) in &статистика {
        print!("{}: {}", элемент, значение)
    }
} test {
    // Тест индексирования
    let тестовыеПользователи = vec![
        Пользователь { id: 1, имя: "Тест1".to_string(), возраст: 25, отдел: "КомандаA".to_string() },
        Пользователь { id: 2, имя: "Тест2".to_string(), возраст: 30, отдел: "КомандаB".to_string() },
    ]
    
    let картаID: Map<u32, &Пользователь> = тестовыеПользователи.iter()
        .map(|u| (u.id, u))
        .collect()
    
    assert картаID.get(&1).unwrap().имя == "Тест1"
    assert картаID.get(&2).unwrap().отдел == "КомандаB"
    
    // Тест мультииндекса
    let индекс = МультиИндекс::new(тестовыеПользователи)
    assert индекс.найтиПоID(1).is_some()
    assert индекс.найтиПоОтделу("КомандаA").len() == 1
    assert индекс.найтиПоДиапазонуВозраста(25, 35).len() == 2
}

индексированиеДанных()
примерМультиИндекса()

✅ Освоение Map

Map — одна из самых полезных структур данных в Топазе:

✅ Когда использовать Map:

  • Хранение данных ключ-значение
  • Когда нужен быстрый поиск
  • Индексирование данных и группировка
  • Реализация кеша и мемоизации

⚠️ Соображения:

  • Выбор подходящих типов ключей (учет производительности хеширования)
  • Управление использованием памяти (для больших наборов данных)
  • Учет параллелизма (в многопоточных средах)
  • Обеспечение неизменности ключей

🚀 Преимущества Map в Топазе:

  • Гарантия типобезопасности
  • Эффективные алгоритмы хеширования
  • Гибкий API Entry
  • Безопасное управление памятью

Испытайте эффективное управление данными с Map! 🗝️✨