使用散列映射和向量,创建文本界面,允许用户向公司的部门添加员工姓名。例如,“添加萨利到工程”或“添加Amir到销售”。然后让用户按部门检索所有人员或公司所有人员的列表,并按字母顺序排序。
最近,我非常喜欢学习一些锈蚀知识和阅读“锈书”,并希望从第8章中得到一些关于我对这个挑战的答案的反馈。
我故意把事情做得很简短和简单--我已经从字面上回答了这个问题,从我的测试中可以看出,所有的标准都满足了。
我将这些部门硬编码到hashmap中,并且我没有非常努力地处理边缘情况或不适当的输入。用户还必须输入非常笨重的命令和准确的措辞。
该界面并不是超级用户友好的,因为在每个命令之后,循环会重新启动,每次都会显示欢迎消息。
请随时提供上述任何一个反馈,但要知道,我至少意识到了这些问题。
我最关心的是惯用的锈蚀和代码结构。
是否有比if / else if / else更好的方法来处理各种情况?
为了可读性和我自己的理智,我不想在主函数中嵌套太多的循环。如果我想让UX变得更加无缝,那么为可能被反复调用的每个命令创建一个函数,比如添加员工、查看部门以及内部循环,会有意义吗?
还有什么能突出我做错了什么吗?
有什么我做得对的吗?
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");
}
}
}发布于 2023-02-10 16:43:36
它已经很好了,但有几件事我会改变。首先,我介绍了使main变得更短的不同方法。
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的键值对,这比两次散列略高一些。
您可以简单地使用一个多行字符串来消除换行符:
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'."
);最重要的是,由于问题在于不同字符串模式的匹配,因此我使用模式匹配来实现:
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,并听取它的建议。
以下是供参考的全部主要内容:
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")
}
}
}
```https://codereview.stackexchange.com/questions/283121
复制相似问题