Exercício: Usar um mapa de hash para rastrear pedidos
Neste exercício, você vai modificar um programa de fábrica de carros para usar um mapa de hash.
Vamos usar a chave de mapa de hash, pares de valor para acompanhar detalhes sobre os pedidos de carro e para exibir a saída. Uma vez mais, o seu desafio é concluir o código de exemplo para que ele seja compilado e executado.
Para trabalhar no código de exemplo deste exercício, você tem duas opções:
- Copie o código e edite-o em seu ambiente de desenvolvimento local.
- Abra o código em um Rust Playground preparado.
Observação
No código de exemplo, procure a macro todo!
. Essa macro indica o código que precisa ser concluído ou atualizado.
Carregar o programa atual
A primeira etapa é obter o código do programa existente.
Abra o código do programa para edição. O código inclui declarações de tipo de dados e definições para as funções
car_quality
,car_factory
emain
.Copie o código a seguir e edite-o em seu ambiente de desenvolvimento local
ou abra o código em um Rust Playground preparado.#[derive(PartialEq, Debug)] struct Car { color: String, motor: Transmission, roof: bool, age: (Age, u32) } #[derive(PartialEq, Debug)] enum Transmission { Manual, SemiAuto, Automatic } #[derive(PartialEq, Debug)] enum Age { New, Used } // Get the car quality by testing the value of the input argument // - miles (u32) // Return tuple with car age ("New" or "Used") and mileage fn car_quality (miles: u32) -> (Age, u32) { // Check if car has accumulated miles // Return tuple early for Used car if miles > 0 { return (Age::Used, miles); } // Return tuple for New car, no need for "return" keyword or semicolon (Age::New, miles) } // Build "Car" using input arguments fn car_factory(order: i32, miles: u32) -> Car { let colors = ["Blue", "Green", "Red", "Silver"]; // Prevent panic: Check color index for colors array, reset as needed // Valid color = 1, 2, 3, or 4 // If color > 4, reduce color to valid index let mut color = order as usize; if color > 4 { // color = 5 --> index 1, 6 --> 2, 7 --> 3, 8 --> 4 color = color - 4; } // Add variety to orders for motor type and roof type let mut motor = Transmission::Manual; let mut roof = true; if order % 3 == 0 { // 3, 6, 9 motor = Transmission::Automatic; } else if order % 2 == 0 { // 2, 4, 8, 10 motor = Transmission::SemiAuto; roof = false; } // 1, 5, 7, 11 // Return requested "Car" Car { color: String::from(colors[(color-1) as usize]), motor: motor, roof: roof, age: car_quality(miles) } } fn main() { // Initialize counter variable let mut order = 1; // Declare a car as mutable "Car" struct let mut car: Car; // Order 6 cars, increment "order" for each request // Car order #1: Used, Hard top car = car_factory(order, 1000); println!("{}: {:?}, Hard top = {}, {:?}, {}, {} miles", order, car.age.0, car.roof, car.motor, car.color, car.age.1); // Car order #2: Used, Convertible order = order + 1; car = car_factory(order, 2000); println!("{}: {:?}, Hard top = {}, {:?}, {}, {} miles", order, car.age.0, car.roof, car.motor, car.color, car.age.1); // Car order #3: New, Hard top order = order + 1; car = car_factory(order, 0); println!("{}: {:?}, Hard top = {}, {:?}, {}, {} miles", order, car.age.0, car.roof, car.motor, car.color, car.age.1); // Car order #4: New, Convertible order = order + 1; car = car_factory(order, 0); println!("{}: {:?}, Hard top = {}, {:?}, {}, {} miles", order, car.age.0, car.roof, car.motor, car.color, car.age.1); // Car order #5: Used, Hard top order = order + 1; car = car_factory(order, 3000); println!("{}: {:?}, Hard top = {}, {:?}, {}, {} miles", order, car.age.0, car.roof, car.motor, car.color, car.age.1); // Car order #6: Used, Hard top order = order + 1; car = car_factory(order, 4000); println!("{}: {:?}, Hard top = {}, {:?}, {}, {} miles", order, car.age.0, car.roof, car.motor, car.color, car.age.1); }
Compile o programa. Verifique se o código é compilado e executado antes de prosseguir para a próxima seção.
Você deve ver o seguinte resultado:
1: Used, Hard top = true, Manual, Blue, 1000 miles
2: Used, Hard top = false, SemiAuto, Green, 2000 miles
3: New, Hard top = true, Automatic, Red, 0 miles
4: New, Hard top = false, SemiAuto, Silver, 0 miles
5: Used, Hard top = true, Manual, Blue, 3000 miles
6: Used, Hard top = true, Automatic, Green, 4000 miles
Adicione um mapa de hash para rastrear os detalhes do pedido
O programa atual preenche cada pedido de carro e imprime um resumo após a conclusão de cada pedido. Cada chamada para a função car_factory
atende a um pedido retornando uma struct Car
com os detalhes do pedido. O resultado é armazenado na variável car
.
Como você já percebeu, o programa carece de algumas funcionalidades importantes. Não estamos acompanhando todos os pedidos. A variável car
contém apenas os detalhes do pedido atual. Sempre que a variável car
for atualizada com o resultado da função car_factory
, os detalhes do pedido anterior serão substituídos.
Precisamos atualizar o programa para acompanhar todos os pedidos, como em um sistema de arquivamento. Para essa finalidade, vamos definir um mapa de hash com pares <K, V>. As chaves de mapa de hash corresponderão aos números de pedido de carro. Os valores do mapa de hash serão os detalhes do pedido para cada um conforme definido em um struct Car
.
Para definir o mapa de hash, adicione o seguinte código no início da função
main
, logo após a chave de abertura{
:// Initialize a hash map for the car orders // - Key: Car order number, i32 // - Value: Car order details, Car struct use std::collections::HashMap; let mut orders: HashMap<i32, Car> = HashMap;
Corrija os problemas de sintaxe na instrução que cria o mapa de hash
orders
.Dica
Você está criando um mapa de hash do zero, portanto, provavelmente deseja usar o método
new()
.Compile o programa. Verifique se o código foi compilado antes de prosseguir para a próxima seção. Você pode ignorar mensagens de aviso do compilador.
Adicionar valores ao mapa de hash
A próxima etapa é adicionar cada pedido de carro atendido ao mapa de hash.
Na função main
, chamamos a função car_factory
para cada pedido de carro. Depois que o pedido for cumprido, chamamos a macro println!
para mostrar os detalhes do pedido armazenados na variável car
:
// Car order #1: Used, Hard top
car = car_factory(order, 1000);
println!("{}: {}, Hard top = {}, {:?}, {}, {} miles", order, car.age.0, car.roof, car.motor, car.color, car.age.1);
...
// Car order #6: Used, Hard top
order = order + 1;
car = car_factory(order, 4000);
println!("{}: {}, Hard top = {}, {:?}, {}, {} miles", order, car.age.0, car.roof, car.motor, car.color, car.age.1);
Vamos revisar essas instruções de código para trabalhar com nosso novo mapa de hash:
- Manteremos as chamadas para a função
car_factory
. Cada structCar
retornado será armazenado como parte do par <K, V> no mapa de hash. - Vamos atualizar as chamadas para a macro
println!
para mostrar os detalhes do pedido conforme eles são armazenados no mapa de hash.
Na função
main
, localize as chamadas para a funçãocar_factory
e as chamadas que o acompanham para a macroprintln!
:// Car order #1: Used, Hard top car = car_factory(order, 1000); println!("{}: {}, Hard top = {}, {:?}, {}, {} miles", order, car.age.0, car.roof, car.motor, car.color, car.age.1); ... // Car order #6: Used, Hard top order = order + 1; car = car_factory(order, 4000); println!("{}: {}, Hard top = {}, {:?}, {}, {} miles", order, car.age.0, car.roof, car.motor, car.color, car.age.1);
Substitua o conjunto completo de instruções para todos os pedidos de carros pelo seguinte código revisado:
// Car order #1: Used, Hard top car = car_factory(order, 1000); orders(order, car); println!("Car order {}: {:?}", order, orders.get(&order)); // Car order #2: Used, Convertible order = order + 1; car = car_factory(order, 2000); orders(order, car); println!("Car order {}: {:?}", order, orders.get(&order)); // Car order #3: New, Hard top order = order + 1; car = car_factory(order, 0); orders(order, car); println!("Car order {}: {:?}", order, orders.get(&order)); // Car order #4: New, Convertible order = order + 1; car = car_factory(order, 0); orders(order, car); println!("Car order {}: {:?}", order, orders.get(&order)); // Car order #5: Used, Hard top order = order + 1; car = car_factory(order, 3000); orders(order, car); println!("Car order {}: {:?}", order, orders.get(&order)); // Car order #6: Used, Hard top order = order + 1; car = car_factory(order, 4000); orders(order, car); println!("Car order {}: {:?}", order, orders.get(&order));
Se você tentar compilar seu programa agora, você verá erros de compilação. Há um problema de sintaxe nas instruções que adicionam os pares <K, V> ao mapa de hash
orders
. Você vê o problema? Vá em frente e corrija o problema em cada instrução que adiciona um pedido ao mapa de hash.Dica
Não podemos atribuir valores diretamente ao mapa de hash
orders
. Precisamos usar um método para fazer as inserções.
Execute o programa
Depois que o programa for compilado com êxito, você verá a seguinte saída:
Car order 1: Some(Car { color: "Blue", motor: Manual, roof: true, age: ("Used", 1000) })
Car order 2: Some(Car { color: "Green", motor: SemiAuto, roof: false, age: ("Used", 2000) })
Car order 3: Some(Car { color: "Red", motor: Automatic, roof: true, age: ("New", 0) })
Car order 4: Some(Car { color: "Silver", motor: SemiAuto, roof: false, age: ("New", 0) })
Car order 5: Some(Car { color: "Blue", motor: Manual, roof: true, age: ("Used", 3000) })
Car order 6: Some(Car { color: "Green", motor: Automatic, roof: true, age: ("Used", 4000) })
Observe que a saída do código revisado é diferente. A macro println!
exibe o conteúdo do struct Car
mostrando cada valor e o nome do campo correspondente.
No próximo exercício, usaremos as expressões de loop para reduzir a redundância no código.
Solução
Você pode comparar a saída do programa à solução deste exercício neste Rust Playground.