I tried completing the practice for 8.3. The code works but there are parts that I find ugly. I had to check Option<> for adding names which introduced unpleasant nested loops. I also had to clone all the department keys so I can use &mut on the hashmap to sort them. Please share any improvements I can make.
use std::io::Write;
use std::str::SplitWhitespace;
use std::collections::HashMap;
fn main() {
println!(">>> Welcome to Company Manager!!!");
println!(">>> Enter commands to start. Enter \"help\" for list of commands.");
// department and list of names
let mut department_data: HashMap<String, Vec<String>> = HashMap::new();
let mut is_running = true;
loop{
let mut input = String::new();
if let Err(_) = std::io::stdin().read_line(&mut input){
println!(">>> Please try again!!");
continue;
}
let mut word_iter = input.split_whitespace();
if let Some(command_word) = word_iter.next(){
match command_word {
"add" => on_add(word_iter, &mut department_data),
"help" => on_help(word_iter),
"show" => on_show(word_iter, &mut department_data),
"quit" => on_quit(word_iter, &mut is_running),
_ => println!(">>> Invalid Command!")
}
}
if !is_running {
break;
}
}
}
fn on_quit(mut word_iter: SplitWhitespace<'_>, is_running: &mut bool){
if let Some(_) = word_iter.next() {
// not help command
println!(">>> Invalid Command!");
return;
}
*is_running = false;
}
fn on_help(mut word_iter: SplitWhitespace<'_>){
if let Some(_) = word_iter.next() {
// not help command
println!(">>> Invalid Command!");
return;
}
println!(">>> Use \"add <name> to <department>\" command to add an employee to a department");
println!(">>> Use \"show <department>\" command to show all employees in a department");
println!(">>> Use \"show all\" command to show all departments and employees");
println!(">>> Use \"quit\" command to quit the program");
}
fn on_add(mut word_iter: SplitWhitespace<'_>, hash: &mut HashMap<String, Vec<String>>){
if let Some(name) = word_iter.next(){
if let Some(require_to) = word_iter.next(){
if require_to == "to"{
if let Some(department) = word_iter.next(){
(*hash).entry(department.to_string()).or_insert(Vec::new()).push(name.to_string());
println!(">>>>> Added {name} to department {department}!");
return;
}
}
}
}
println!(">>> Use \"add <name> to <department>\" command to add a person to a department");
}
fn on_show(mut word_iter: SplitWhitespace<'_>, hash: &mut HashMap<String, Vec<String>>){
if let Some(word) = word_iter.next(){
if let None = word_iter.next(){
match word{
"all" => {
let mut dep_vec = Vec::new();
for departments in hash.keys(){
dep_vec.push(departments.clone());
}
dep_vec.sort();
for dep in dep_vec {
show_department(&dep, hash);
}
return;
},
_ => {
show_department(word, hash);
return;
}
}
}
}
println!(">>> Use \"show all\" command to show all departments and employees");
println!(">>> Use \"show <department>\" command to show all employees in a department");
}
fn show_department(department: &str, hash: &mut HashMap<String, Vec<String>>){
if let Some(vec) = hash.get_mut(department){
vec.sort();
print!(">>>>> Employees in {}: ", department);
for name in vec {
print!(" {name} ");
}
print!("\n");
std::io::stdout().flush().expect("unknown error in text output");
return;
}
println!(">>> Invalid Department!");
}