연습: 해시 맵을 사용하여 주문 추적
이 연습에서는 해시 맵을 사용하도록 자동차 공장 프로그램을 수정합니다.
해시 맵 키, 값 쌍을 사용 하 여 자동차 주문에 대 한 세부 정보를 추적 하 고 출력을 표시 합니다. 이번에도 도전 과제는 샘플 코드를 컴파일되고 실행되도록 완료하는 것입니다.
이 연습의 샘플 코드를 작업할 때 다음 두 가지 옵션이 있습니다.
- 로컬 개발 환경에서 코드를 복사하고 편집합니다.
- 준비된 Rust Playground에서 코드를 엽니다.
참고
샘플 코드에서 todo!
매크로를 찾습니다. 이 매크로는 완료하거나 업데이트해야 하는 코드를 나타냅니다.
현재 프로그램 로드
첫 번째 단계는 기존 프로그램 코드를 가져오는 것입니다.
기존 프로그램 코드를 편집용으로 엽니다. 코드에는 데이터 형식 선언 및
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); }
프로그램을 빌드합니다. 다음 섹션을 계속 하기 전에 코드를 컴파일하고 실행 해야 합니다.
다음 출력이 표시됩니다.
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
구조체에 정의된 각각에 대한 주문 세부 정보입니다.
해시 맵을 정의하려면 여는 중괄호
{
바로 뒤에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;
orders
해시 맵을 만드는 문에서 구문 문제를 해결합니다.팁
해시 맵을 처음부터 만들므로
new()
메서드를 사용해야 합니다.프로그램을 빌드합니다. 다음 섹션으로 진행하기 전에 코드가 컴파일되는지 확인합니다. 컴파일러의 경고 메시지는 무시해도 됩니다.
해시 맵에 값 추가
다음 단계는 각 충족 된 자동차 순서를 해시 맵에 추가 하는 것입니다.
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!
매크로에 대한 호출을 업데이트하여 해시 맵에 저장된 주문 세부 정보를 표시합니다.
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);
모든 자동차 주문의 전체 문 집합을 다음 수정 된 코드로 바꿉니다.
// 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));
지금 프로그램을 빌드하려고 하면 컴파일 오류가 표시됩니다.
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에서 이 연습의 솔루션과 프로그램 출력을 비교할 수 있습니다.