Types de clés alternatifs/ personnalisés

Beginner

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

Introduction

Dans ce laboratoire, nous explorons l'utilisation de types de clés alternatifs/ personnalisés dans le HashMap de Rust, qui peut inclure des types qui implémentent les traits Eq et Hash tels que bool, int, uint, String et &str. De plus, nous pouvons implémenter ces traits pour des types personnalisés en utilisant l'attribut #[derive(PartialEq, Eq, Hash)], leur permettant d'être utilisés comme clés dans un HashMap.

Note : Si le laboratoire ne spécifie pas de nom de fichier, vous pouvez utiliser n'importe quel nom de fichier que vous voulez. Par exemple, vous pouvez utiliser main.rs, le compiler et l'exécuter avec rustc main.rs &&./main.

Types de clés alternatifs/ personnalisés

N'importe quel type qui implémente les traits Eq et Hash peut être une clé dans un HashMap. Cela inclut :

  • bool (quoique pas très utile car il n'y a que deux clés possibles)
  • int, uint et toutes leurs variantes
  • String et &str (astuce : vous pouvez avoir un HashMap indexé par String et appeler .get() avec un &str)

Notez que f32 et f64 n'implémentent pas Hash, probablement parce que les erreurs de précision des nombres à virgule flottante rendraient l'utilisation de ces types comme clés de hashmap très sujette à des erreurs.

Toutes les classes de collection implémentent Eq et Hash si leur type contenu implémente également respectivement Eq et Hash. Par exemple, Vec<T> implémentera Hash si T implémente Hash.

Vous pouvez facilement implémenter Eq et Hash pour un type personnalisé avec une seule ligne : #[derive(PartialEq, Eq, Hash)]

Le compilateur s'en chargera du reste. Si vous voulez plus de contrôle sur les détails, vous pouvez implémenter Eq et/ou Hash vous-même. Ce guide ne couvrira pas les détails de l'implémentation de Hash.

Pour tester l'utilisation d'un struct dans un HashMap, essayons de créer un système de connexion d'utilisateur très simple :

use std::collections::HashMap;

// Eq nécessite que vous dérivez PartialEq sur le type.
#[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: "j.everyman@email.com",
    };

    accounts.insert(account, account_info);

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

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

Résumé

Félicitations ! Vous avez terminé le laboratoire sur les Types de clés alternatifs/ personnalisés. Vous pouvez pratiquer d'autres laboratoires dans LabEx pour améliorer vos compétences.