연습: 해시 맵을 사용하여 주문 추적

완료됨

이 연습에서는 해시 맵을 사용하도록 자동차 공장 프로그램을 수정합니다.

해시 맵 키, 값 쌍을 사용 하 여 자동차 주문에 대 한 세부 정보를 추적 하 고 출력을 표시 합니다. 이번에도 도전 과제는 샘플 코드를 컴파일되고 실행되도록 완료하는 것입니다.

이 연습의 샘플 코드를 작업할 때 다음 두 가지 옵션이 있습니다.

  • 로컬 개발 환경에서 코드를 복사하고 편집합니다.
  • 준비된 Rust Playground에서 코드를 엽니다.

참고

샘플 코드에서 todo! 매크로를 찾습니다. 이 매크로는 완료하거나 업데이트해야 하는 코드를 나타냅니다.

현재 프로그램 로드

첫 번째 단계는 기존 프로그램 코드를 가져오는 것입니다.

  1. 기존 프로그램 코드를 편집용으로 엽니다. 코드에는 데이터 형식 선언 및 car_quality, car_factory, main 함수의 정의가 포함되어 있습니다.

    다음 코드를 복사하여 로컬 개발 환경에서 편집하거나
    준비된 Rust Playground에서 코드를 엽니다.

    #[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);
    }
    
  2. 프로그램을 빌드합니다. 다음 섹션을 계속 하기 전에 코드를 컴파일하고 실행 해야 합니다.

다음 출력이 표시됩니다.

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

해시 맵을 추가하여 주문 세부 정보 추적

현재 프로그램은 각 자동차 순서를 충족 하 고 각 주문이 완료 된 후 요약을 출력 합니다. car_factory 함수를 호출할 때마다 Car 구조체를 주문 세부 정보와 함께 반환하여 주문을 수행합니다. 결과는 car 변수에 저장됩니다.

아마도이 프로그램에는 몇 가지 중요 한 기능이 부족 합니다. 모든 주문을 추적 하지는 않습니다. car 변수는 현재 주문의 세부 정보만을 유지합니다. car 변수가 car_factory 함수의 결과로 업데이트될 때마다 이전 주문의 세부 정보를 덮어씁니다.

프로그램 시스템에서와 같은 모든 주문을 추적 하려면 프로그램을 업데이트 해야 합니다. 이를 위해 <K, V> 쌍으로 해시 맵을 정의합니다. 해시 맵 키는 자동차 주문 번호에 해당 합니다. 해시 맵 값은 Car 구조체에 정의된 각각에 대한 주문 세부 정보입니다.

  1. 해시 맵을 정의하려면 여는 중괄호 { 바로 뒤에 main 함수 시작 부분에 다음 코드를 추가합니다.

        // 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;
    
  2. orders 해시 맵을 만드는 문에서 구문 문제를 해결합니다.

    해시 맵을 처음부터 만들므로 new() 메서드를 사용해야 합니다.

  3. 프로그램을 빌드합니다. 다음 섹션으로 진행하기 전에 코드가 컴파일되는지 확인합니다. 컴파일러의 경고 메시지는 무시해도 됩니다.

해시 맵에 값 추가

다음 단계는 각 충족 된 자동차 순서를 해시 맵에 추가 하는 것입니다.

main 기능에서 각 자동차 주문에 대해 car_factory 기능을 호출합니다. 주문이 수행되면, println! 매크로를 호출하여 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);

새 해시 맵을 사용 하기 위해 다음 코드 문을 수정 하겠습니다.

  • car_factory 함수에 대한 호출을 유지합니다. 반환된 각 Car 구조체는 해시 맵에서 <K, V> 쌍의 일부로 저장됩니다.
  • println! 매크로에 대한 호출을 업데이트하여 해시 맵에 저장된 주문 세부 정보를 표시합니다.
  1. main 함수에서 car_factory 함수에 대한 호출과 println! 매크로에 대한 호출을 찾습니다.

        // 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);
    
  2. 모든 자동차 주문의 전체 문 집합을 다음 수정 된 코드로 바꿉니다.

        // 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));
    
  3. 지금 프로그램을 빌드하려고 하면 컴파일 오류가 표시됩니다. orders 해시 맵에 <K, V> 쌍을 추가하는 문에 구문 문제가 있습니다. 문제가 보이나요? 계속 해 서 해시 맵에 주문을 추가 하는 각 문의 문제를 해결 합니다.

    orders 해시 맵에 직접 값을 할당할 수 없습니다. 삽입하려면 메서드를 사용해야 합니다.

프로그램 실행

프로그램이 성공적으로 빌드되면 다음과 같은 출력이 표시 됩니다.

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) })

수정 된 코드의 출력은 다릅니다. println! 매크로는 각 값과 해당 필드 이름을 표시하여 Car 구조체의 내용을 표시합니다.

다음 연습에서는 루프 식을 사용 하 여 코드의 중복성을 줄입니다.

솔루션

Rust Playground에서 이 연습의 솔루션과 프로그램 출력을 비교할 수 있습니다.