Bài tập: Bộ đếm

Trong bài tập này, ta sẽ chuyển một cấu trúc dữ liệu đơn giản thành một cấu trúc dữ liệu generic. Chúng ta sẽ sử dụng một std::collections::HashMap để theo dõi các giá trị đã xuất hiện và số lần xuất hiện của mỗi giá trị.

Phiên bản đầu tiên của Counter chỉ hoạt động với các giá trị kiểu u32. Hãy biến struct Counter và các hàm của nó thành generic, để Counter có thể theo dõi bất kỳ kiểu dữ liệu nào.

Nếu bạn hoàn thành sớm, hãy thử sử dụng hàm entry để giảm đi một nửa số lần thực hiện hash lookup cần thiết để thực hiện hàm count.

use std::collections::HashMap;

/// Counter đếm số lần mỗi giá trị kiểu T xuất hiện.
struct Counter {
    values: HashMap<u32, u64>,
}

impl Counter {
    /// Khởi tạo một Counter mới.
    fn new() -> Self {
        Counter {
            values: HashMap::new(),
        }
    }

    /// Tăng số lần xuất hiện của giá trị đã cho.
    fn count(&mut self, value: u32) {
        if self.values.contains_key(&value) {
            *self.values.get_mut(&value).unwrap() += 1;
        } else {
            self.values.insert(value, 1);
        }
    }

    /// Trả về số lần mà giá trị đã cho đã xuất hiện.
    fn times_seen(&self, value: u32) -> u64 {
        self.values.get(&value).copied().unwrap_or_default()
    }
}

fn main() {
    let mut ctr = Counter::new();
    ctr.count(13);
    ctr.count(14);
    ctr.count(16);
    ctr.count(14);
    ctr.count(14);
    ctr.count(11);

    for i in 10..20 {
        println!("{} xuất hiện {} lần", ctr.times_seen(i), i);
    }

    let mut strctr = Counter::new();
    strctr.count("táo");
    strctr.count("cam");
    strctr.count("táo");
    println!("có {} quả táo", strctr.times_seen("táo"));
}