Ha

Hashmap em Rust

{one: "1 exercício", many: "%{count} exercícios", other: "%{count} exercícios"}

Sobre Hashmap

Um HashMap é um contentor que pode ser usado para armazenar pares chave-valor. Noutras linguagens de programação, esta estrutura de dados é por vezes chamada array associativo ou tabela de dispersão. O mapa contém um conjunto de chaves, cada uma associada a um valor específico. O utilizador pode obter um valor armazenado passando a chave adequada. Também pode inserir e eliminar chaves e os valores associados.

HashMap é uma coleção genérica (como a maioria das coleções da biblioteca padrão) e, por isso, suporta uma grande variedade de tipos como chaves, incluindo estruturas e tuplos definidos pelo utilizador. Os seus valores podem ser de qualquer tipo.

Criar um HashMap

Um HashMap é criado com a função HashMap::new(). O excerto de código abaixo cria um HashMap com nomes de equipas associados a pontuações.

use std::collections::HashMap;

let mut scores = HashMap::new();

scores.insert(String::from("Blue"), 10);
scores.insert(String::from("Yellow"), 50);

Aceder aos valores num HashMap

Se souberes que um valor existe num HashMap, podes usar o operador de indexação ([]). Para obter a pontuação da equipa azul, por exemplo, podemos usar scores["Blue"]. No entanto, se o par chave-valor adequado não existir no HashMap, esta operação entra em pânico.

Além do operador de indexação, há duas outras formas de aceder a valores armazenados num HashMap. A primeira é usar a função membro get:

if let Some(blue_score) = scores.get("Blue") {
    println!("Blue scored: {blue_score} \n");
}

get acede ao valor armazenado para a chave pedida. Devolve None se a chave fornecida não existir no HashMap, e Some(value) se a chave existir. Para saberes mais sobre Option em Rust, consulta o conceito Option.

A outra forma de aceder a valores armazenados num HashMap é usar o método entry. O método entry (ou a API entry) devolve uma referência à entrada do par chave-valor no HashMap. A entrada representa o estado desta chave no HashMap. Se a chave não existir, não há valor na entrada (e permite inserir um).

let mut vote_counter: HashMap<_, usize> = HashMap::new();
let votes = ["Blue", "Red", "Red", "Blue", "Red", "Blue", "Blue"];
for vote in votes {
    let count = vote_counter.entry(vote).or_default();
    *count += 1;
}

println!("{vote_counter:#?}");

Esta API torna certos padrões comuns de acesso muito convenientes; há um conceito inteiro (Entry API) dedicado a ela.

Eficiência

Os HashMap são relativamente rápidos e têm complexidade constante amortizada (O(1)) para todas as operações que envolvem uma única chave.

Limites de traits

Um HashMap é uma estrutura de dados genérica, o que significa que suporta tipos arbitrários como chaves e valores, com apenas uma restrição: para um tipo ser usado como tipo de chave, tem de ter uma implementação para dois traits: Eq e Hash. Não há limites de traits no tipo do valor.

Editar via GitHub A ligação abre numa nova janela ou separador