Альтернативные/Настраиваемые Типы Ключей

RustRustBeginner
Практиковаться сейчас

This tutorial is from open-source community. Access the source code

💡 Этот учебник переведен с английского с помощью ИИ. Чтобы просмотреть оригинал, вы можете перейти на английский оригинал

Введение

В этом лабораторном задании мы исследуем использование альтернативных/настраиваемых типов ключей в HashMap языка Rust, которые могут включать типы, реализующие трейты Eq и Hash, такие как bool, int, uint, String и &str. Кроме того, мы можем реализовать эти трейты для пользовательских типов, используя атрибут #[derive(PartialEq, Eq, Hash)], что позволяет использовать их в качестве ключей в HashMap.

Примечание: Если в лабораторном задании не указано имя файла, вы можете использовать любое имя файла, которое хотите. Например, вы можете использовать main.rs, скомпилировать и запустить его с помощью команды rustc main.rs &&./main.

Альтернативные/настраиваемые типы ключей

Любой тип, реализующий трейты Eq и Hash, может быть ключом в HashMap. Это включает в себя:

  • bool (хотя это не очень полезно, так как есть только два возможных ключа)
  • int, uint и все их вариации
  • String и &str (хитрость: вы можете иметь HashMap, ключи которого типа String, и вызывать .get() с &str)

Обратите внимание, что f32 и f64 не реализуют Hash, вероятно, потому что ошибки точности с плавающей запятой сделают использование их в качестве ключей в хэш-мапе крайне ошибочным.

Все классы коллекций реализуют Eq и Hash, если их содержащий тип также соответственно реализует Eq и Hash. Например, Vec<T> реализует Hash, если T реализует Hash.

Вы можете легко реализовать Eq и Hash для пользовательского типа всего за одну строку: #[derive(PartialEq, Eq, Hash)]

Компилятор сделает остальное. Если вы хотите более тщательно контролировать детали, вы можете реализовать Eq и/или Hash самостоятельно. В этом руководстве не будут рассмотрены детали реализации Hash.

Для эксперимента с использованием struct в HashMap давайте попробуем сделать очень простую систему входа пользователя:

use std::collections::HashMap;

// Eq требует, чтобы вы выводили PartialEq для типа.
#[derive(PartialEq, Eq, Hash)]
struct Account<'a>{
    username: &'a str,
    password: &'a str,
}

struct AccountInfo<'a>{
    name: &'a str,
    email: &'a str,
}

type Accounts<'a> = HashMap<Account<'a>, AccountInfo<'a>>;

fn try_logon<'a>(accounts: &Accounts<'a>,
        username: &'a str, password: &'a str){
    println!("Username: {}", username);
    println!("Password: {}", password);
    println!("Attempting logon...");

    let logon = Account {
        username,
        password,
    };

    match accounts.get(&logon) {
        Some(account_info) => {
            println!("Successful logon!");
            println!("Name: {}", account_info.name);
            println!("Email: {}", account_info.email);
        },
        _ => println!("Login failed!"),
    }
}

fn main(){
    let mut accounts: Accounts = HashMap::new();

    let account = Account {
        username: "j.everyman",
        password: "password123",
    };

    let account_info = AccountInfo {
        name: "John Everyman",
        email: "[email protected]",
    };

    accounts.insert(account, account_info);

    try_logon(&accounts, "j.everyman", "psasword123");

    try_logon(&accounts, "j.everyman", "password123");
}

Резюме

Поздравляем! Вы завершили лабораторную работу по Альтернативным/Настраиваемым Типам Ключей. Вы можете практиковаться в более многих лабораторных работах в LabEx, чтобы улучшить свои навыки.