首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >铁锈书第8章-员工管理的文字界面

铁锈书第8章-员工管理的文字界面
EN

Code Review用户
提问于 2023-02-07 18:01:20
回答 1查看 69关注 0票数 3

使用散列映射和向量,创建文本界面,允许用户向公司的部门添加员工姓名。例如,“添加萨利到工程”或“添加Amir到销售”。然后让用户按部门检索所有人员或公司所有人员的列表,并按字母顺序排序。

最近,我非常喜欢学习一些锈蚀知识和阅读“锈书”,并希望从第8章中得到一些关于我对这个挑战的答案的反馈。

我故意把事情做得很简短和简单--我已经从字面上回答了这个问题,从我的测试中可以看出,所有的标准都满足了。

我将这些部门硬编码到hashmap中,并且我没有非常努力地处理边缘情况或不适当的输入。用户还必须输入非常笨重的命令和准确的措辞。

该界面并不是超级用户友好的,因为在每个命令之后,循环会重新启动,每次都会显示欢迎消息。

请随时提供上述任何一个反馈,但要知道,我至少意识到了这些问题。

我最关心的是惯用的锈蚀和代码结构。

是否有比if / else if / else更好的方法来处理各种情况?

为了可读性和我自己的理智,我不想在主函数中嵌套太多的循环。如果我想让UX变得更加无缝,那么为可能被反复调用的每个命令创建一个函数,比如添加员工、查看部门以及内部循环,会有意义吗?

还有什么能突出我做错了什么吗?

有什么我做得对的吗?

代码语言:javascript
复制
use std::collections::HashMap;
use std::io;

fn main() {
    let mut company: HashMap<String, Vec<String>> = HashMap::new();

    company.insert("engineering".to_string(), Vec::new());
    company.insert("operations".to_string(), Vec::new());
    company.insert("sales".to_string(), Vec::new());

    loop {
        println!("Welcome! What would you like to do?\n 
                  To add employee to a department, type 'Add <employee name> to <department name> (engineering, operations, or sales),\n 
                  To view employees in a department, type 'View department <department name>',\n
                  To view all employees by department, type 'View all',
                  To exit, type 'exit'.
        ");

        let mut entry = String::new();
        io::stdin()
            .read_line(&mut entry)
            .expect("Failed to read line");

        let entry: &str = entry.trim();
        let mut split = entry.split_whitespace();

        if entry.contains("Add") {
            let emp = split.nth(1).unwrap().to_string();
            let dep = split.nth(1).unwrap().to_lowercase();
            println!("{emp} added to {dep}");

            let vec = company.get_mut(&dep).unwrap();
            vec.push(emp);
            vec.sort_by_key(|name| name.to_lowercase());
            println!("{:?}", company)
        } else if entry.contains("View department") {
            let dep = split.nth(2).unwrap().to_lowercase();
            let view = &company[&dep];

            println!("Employees in {dep}:\n");
            for v in view {
                println!("{v}\n");
            }
        } else if entry.contains("View all") {
            for k in company.keys() {
                let view = &company[k];
                println!("Department: {k}");
                for v in view {
                    println!("{v}\n");
                }
            }
        } else if entry == "exit" {
            break;
        } else {
            println!("Please enter a valid option");
        }
    }
}
EN

回答 1

Code Review用户

回答已采纳

发布于 2023-02-10 16:43:36

它已经很好了,但有几件事我会改变。首先,我介绍了使main变得更短的不同方法。

代码语言:javascript
复制
fn view_department(company: &HashMap<String, Vec<String>>, department: &str) {
    println!("Employees in {department}:\n");
    for e in &company[department] {
        println!("{e}\n");
    }
}

fn view_all(company: &HashMap<String, Vec<String>>) {
    for (department, employees) in company {
        println!("Department: {department}");
        for e in employees {
            println!("{e}\n");
        }
    }
}

fn add_employee(company: &mut HashMap<String, Vec<String>>, employee: &str, department: &str) {
    println!("{employee} added to {department}");

    let vec = company.get_mut(department).unwrap();
    vec.push(employee.to_owned());
    vec.sort_by_key(|name| name.to_lowercase());
    println!("{company:?}")
}

注意,我直接迭代hashmap的键值对,这比两次散列略高一些。

您可以简单地使用一个多行字符串来消除换行符:

代码语言:javascript
复制
        println!(
"Welcome! What would you like to do?
To add employee to a department, type 'Add <employee name> to <department name> (engineering, operations, or sales),
To view employees in a department, type 'View department <department name>',
To view all employees by department, type 'View all',
To exit, type 'exit'."
        );

最重要的是,由于问题在于不同字符串模式的匹配,因此我使用模式匹配来实现:

代码语言:javascript
复制
match entry.split_whitespace().collect::<Vec<&str>>().as_slice() {
    ["Add", emp, "to", dep] => add_employee(&mut company, emp, dep),
    ["View", "department", dep] => view_department(&company, dep),
    ["View", "all"] => view_all(&company),
    ["exit"] => break,
    _ => println!("Please enter a valid option")
}

我认为这比包含大量nth和神奇索引的版本更易读。

附带注意:我最初写的是entry.trim().split_whitespace(),但是告诉我trim是不必要的,所以经常使用clippy,并听取它的建议。

以下是供参考的全部主要内容:

代码语言:javascript
复制
fn main() {
    let mut company: HashMap<String, Vec<String>> = HashMap::new();

    company.insert("engineering".to_string(), Vec::new());
    company.insert("operations".to_string(), Vec::new());
    company.insert("sales".to_string(), Vec::new());

    loop {
        println!(
"Welcome! What would you like to do?
To add employee to a department, type 'Add <employee name> to <department name> (engineering, operations, or sales),
To view employees in a department, type 'View department <department name>',
To view all employees by department, type 'View all',
To exit, type 'exit'."
        );

        let mut entry = String::new();
        io::stdin()
            .read_line(&mut entry)
            .expect("Failed to read line");

        match entry.split_whitespace().collect::<Vec<&str>>().as_slice() {
            ["Add", emp, "to", dep] => add_employee(&mut company, emp, dep),
            ["View", "department", dep] => view_department(&company, dep),
            ["View", "all"] => view_all(&company),
            ["exit"] => break,
            _ => println!("Please enter a valid option")
        }
    }
}
```
代码语言:javascript
复制
票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/283121

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档