HashMap exercise, Rust book Ch.8

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
4
down vote

favorite












I'm learning Rust by learning the Rust programming language book. I'm now implementing the solution for the third challenge.




Using a hash map and vectors, create a text interface to allow a user to add employee names to a department in a company. For example, "Add Sally to Engineering" or "Add Amir to Sales." Then let the user retrieve a list of all people in a department or all people in the company by department, sorted alphabetically.




I decided to do a simple UI to enter commands, but the implementation is very naive overall.



Rust is my first systems language. My background is in Ruby and Javascript.



use std::collections::HashMap;
use std::io::self, Write;
use std::str::SplitWhitespace;

fn main()
println!("Welcome to the department interface. Please run a command:");
help();

let mut departments: HashMap<String, Vec<String>> = HashMap::new();

loop
print_promt();
let command = get_command();
let mut command_iter = command.split_whitespace();

match command_iter.next()
Some("add") => match process_add(&mut command_iter)
Ok((employee, department)) =>
let mut employees = departments.entry(department).or_insert(Vec::new());
employees.push(employee);

Err(err) => println!("Error: ", err),
,
Some("help") => help(),
Some("list") => println!(":#?", &departments),
Some("exit") => break,
Some(_) => println!(": Command unknown. Try `help`", command),
None => panic!("We shouldn't be here"),




fn help()
println!("help: show this help.");
println!("exit: exits this program.");
println!("show: shows the deparment structure.");
println!("add: adds an employee to a department");
println!(" - usage: `add <employee name> to <department_name>`");


fn print_promt()
print!("> ");
io::stdout().flush().ok().expect("Couldn't flush stdout!");


// I think this can be made better returning an Enum/Struct with a parsed command.
fn get_command() -> String
let mut command = String::new();
io::stdin()
.read_line(&mut command)
.expect("Couldn't read command!");
command



// The compiler told me to add the lifetime, but I don't understand why (I haven't reached that
// part of the book yet.)
// FIXME `SplitWhitespace` is too specific.
fn process_add<'a>(command: &mut SplitWhitespace) -> Result<(String, String), &'a str>
let mut employee = String::new();
let mut department = String::new();

// For a command "add Ronald Reagan to Old Presidents"
// - Consume the iterator onto `employee` until you find "to""
// - Consume the rest of the iterator onto `department`
// Using two loops feels naive though. I don't like the duplication inside them.
//
// Maybe `String` can be extended and I could add a `push_str_with_separator` method that does
// the extra check.
//
// employee.push_str_with_separator(word);
//
while let Some(word) = command.next()
if word == "to"
break;


if employee.len() > 0
employee.push_str(" ");

employee.push_str(word)


for word in command
if department.len() > 0
department.push_str(" ");

department.push_str(word);


if employee.len() > 0 && department.len() > 0
Ok((employee, department))
else
Err("Could not parse command. Try `add <employee name> to <department name>")








share|improve this question



























    up vote
    4
    down vote

    favorite












    I'm learning Rust by learning the Rust programming language book. I'm now implementing the solution for the third challenge.




    Using a hash map and vectors, create a text interface to allow a user to add employee names to a department in a company. For example, "Add Sally to Engineering" or "Add Amir to Sales." Then let the user retrieve a list of all people in a department or all people in the company by department, sorted alphabetically.




    I decided to do a simple UI to enter commands, but the implementation is very naive overall.



    Rust is my first systems language. My background is in Ruby and Javascript.



    use std::collections::HashMap;
    use std::io::self, Write;
    use std::str::SplitWhitespace;

    fn main()
    println!("Welcome to the department interface. Please run a command:");
    help();

    let mut departments: HashMap<String, Vec<String>> = HashMap::new();

    loop
    print_promt();
    let command = get_command();
    let mut command_iter = command.split_whitespace();

    match command_iter.next()
    Some("add") => match process_add(&mut command_iter)
    Ok((employee, department)) =>
    let mut employees = departments.entry(department).or_insert(Vec::new());
    employees.push(employee);

    Err(err) => println!("Error: ", err),
    ,
    Some("help") => help(),
    Some("list") => println!(":#?", &departments),
    Some("exit") => break,
    Some(_) => println!(": Command unknown. Try `help`", command),
    None => panic!("We shouldn't be here"),




    fn help()
    println!("help: show this help.");
    println!("exit: exits this program.");
    println!("show: shows the deparment structure.");
    println!("add: adds an employee to a department");
    println!(" - usage: `add <employee name> to <department_name>`");


    fn print_promt()
    print!("> ");
    io::stdout().flush().ok().expect("Couldn't flush stdout!");


    // I think this can be made better returning an Enum/Struct with a parsed command.
    fn get_command() -> String
    let mut command = String::new();
    io::stdin()
    .read_line(&mut command)
    .expect("Couldn't read command!");
    command



    // The compiler told me to add the lifetime, but I don't understand why (I haven't reached that
    // part of the book yet.)
    // FIXME `SplitWhitespace` is too specific.
    fn process_add<'a>(command: &mut SplitWhitespace) -> Result<(String, String), &'a str>
    let mut employee = String::new();
    let mut department = String::new();

    // For a command "add Ronald Reagan to Old Presidents"
    // - Consume the iterator onto `employee` until you find "to""
    // - Consume the rest of the iterator onto `department`
    // Using two loops feels naive though. I don't like the duplication inside them.
    //
    // Maybe `String` can be extended and I could add a `push_str_with_separator` method that does
    // the extra check.
    //
    // employee.push_str_with_separator(word);
    //
    while let Some(word) = command.next()
    if word == "to"
    break;


    if employee.len() > 0
    employee.push_str(" ");

    employee.push_str(word)


    for word in command
    if department.len() > 0
    department.push_str(" ");

    department.push_str(word);


    if employee.len() > 0 && department.len() > 0
    Ok((employee, department))
    else
    Err("Could not parse command. Try `add <employee name> to <department name>")








    share|improve this question























      up vote
      4
      down vote

      favorite









      up vote
      4
      down vote

      favorite











      I'm learning Rust by learning the Rust programming language book. I'm now implementing the solution for the third challenge.




      Using a hash map and vectors, create a text interface to allow a user to add employee names to a department in a company. For example, "Add Sally to Engineering" or "Add Amir to Sales." Then let the user retrieve a list of all people in a department or all people in the company by department, sorted alphabetically.




      I decided to do a simple UI to enter commands, but the implementation is very naive overall.



      Rust is my first systems language. My background is in Ruby and Javascript.



      use std::collections::HashMap;
      use std::io::self, Write;
      use std::str::SplitWhitespace;

      fn main()
      println!("Welcome to the department interface. Please run a command:");
      help();

      let mut departments: HashMap<String, Vec<String>> = HashMap::new();

      loop
      print_promt();
      let command = get_command();
      let mut command_iter = command.split_whitespace();

      match command_iter.next()
      Some("add") => match process_add(&mut command_iter)
      Ok((employee, department)) =>
      let mut employees = departments.entry(department).or_insert(Vec::new());
      employees.push(employee);

      Err(err) => println!("Error: ", err),
      ,
      Some("help") => help(),
      Some("list") => println!(":#?", &departments),
      Some("exit") => break,
      Some(_) => println!(": Command unknown. Try `help`", command),
      None => panic!("We shouldn't be here"),




      fn help()
      println!("help: show this help.");
      println!("exit: exits this program.");
      println!("show: shows the deparment structure.");
      println!("add: adds an employee to a department");
      println!(" - usage: `add <employee name> to <department_name>`");


      fn print_promt()
      print!("> ");
      io::stdout().flush().ok().expect("Couldn't flush stdout!");


      // I think this can be made better returning an Enum/Struct with a parsed command.
      fn get_command() -> String
      let mut command = String::new();
      io::stdin()
      .read_line(&mut command)
      .expect("Couldn't read command!");
      command



      // The compiler told me to add the lifetime, but I don't understand why (I haven't reached that
      // part of the book yet.)
      // FIXME `SplitWhitespace` is too specific.
      fn process_add<'a>(command: &mut SplitWhitespace) -> Result<(String, String), &'a str>
      let mut employee = String::new();
      let mut department = String::new();

      // For a command "add Ronald Reagan to Old Presidents"
      // - Consume the iterator onto `employee` until you find "to""
      // - Consume the rest of the iterator onto `department`
      // Using two loops feels naive though. I don't like the duplication inside them.
      //
      // Maybe `String` can be extended and I could add a `push_str_with_separator` method that does
      // the extra check.
      //
      // employee.push_str_with_separator(word);
      //
      while let Some(word) = command.next()
      if word == "to"
      break;


      if employee.len() > 0
      employee.push_str(" ");

      employee.push_str(word)


      for word in command
      if department.len() > 0
      department.push_str(" ");

      department.push_str(word);


      if employee.len() > 0 && department.len() > 0
      Ok((employee, department))
      else
      Err("Could not parse command. Try `add <employee name> to <department name>")








      share|improve this question













      I'm learning Rust by learning the Rust programming language book. I'm now implementing the solution for the third challenge.




      Using a hash map and vectors, create a text interface to allow a user to add employee names to a department in a company. For example, "Add Sally to Engineering" or "Add Amir to Sales." Then let the user retrieve a list of all people in a department or all people in the company by department, sorted alphabetically.




      I decided to do a simple UI to enter commands, but the implementation is very naive overall.



      Rust is my first systems language. My background is in Ruby and Javascript.



      use std::collections::HashMap;
      use std::io::self, Write;
      use std::str::SplitWhitespace;

      fn main()
      println!("Welcome to the department interface. Please run a command:");
      help();

      let mut departments: HashMap<String, Vec<String>> = HashMap::new();

      loop
      print_promt();
      let command = get_command();
      let mut command_iter = command.split_whitespace();

      match command_iter.next()
      Some("add") => match process_add(&mut command_iter)
      Ok((employee, department)) =>
      let mut employees = departments.entry(department).or_insert(Vec::new());
      employees.push(employee);

      Err(err) => println!("Error: ", err),
      ,
      Some("help") => help(),
      Some("list") => println!(":#?", &departments),
      Some("exit") => break,
      Some(_) => println!(": Command unknown. Try `help`", command),
      None => panic!("We shouldn't be here"),




      fn help()
      println!("help: show this help.");
      println!("exit: exits this program.");
      println!("show: shows the deparment structure.");
      println!("add: adds an employee to a department");
      println!(" - usage: `add <employee name> to <department_name>`");


      fn print_promt()
      print!("> ");
      io::stdout().flush().ok().expect("Couldn't flush stdout!");


      // I think this can be made better returning an Enum/Struct with a parsed command.
      fn get_command() -> String
      let mut command = String::new();
      io::stdin()
      .read_line(&mut command)
      .expect("Couldn't read command!");
      command



      // The compiler told me to add the lifetime, but I don't understand why (I haven't reached that
      // part of the book yet.)
      // FIXME `SplitWhitespace` is too specific.
      fn process_add<'a>(command: &mut SplitWhitespace) -> Result<(String, String), &'a str>
      let mut employee = String::new();
      let mut department = String::new();

      // For a command "add Ronald Reagan to Old Presidents"
      // - Consume the iterator onto `employee` until you find "to""
      // - Consume the rest of the iterator onto `department`
      // Using two loops feels naive though. I don't like the duplication inside them.
      //
      // Maybe `String` can be extended and I could add a `push_str_with_separator` method that does
      // the extra check.
      //
      // employee.push_str_with_separator(word);
      //
      while let Some(word) = command.next()
      if word == "to"
      break;


      if employee.len() > 0
      employee.push_str(" ");

      employee.push_str(word)


      for word in command
      if department.len() > 0
      department.push_str(" ");

      department.push_str(word);


      if employee.len() > 0 && department.len() > 0
      Ok((employee, department))
      else
      Err("Could not parse command. Try `add <employee name> to <department name>")










      share|improve this question












      share|improve this question




      share|improve this question








      edited Jul 14 at 21:04









      Jamal♦

      30.1k11114225




      30.1k11114225









      asked Jul 14 at 20:57









      afgomez

      1211




      1211

























          active

          oldest

          votes











          Your Answer




          StackExchange.ifUsing("editor", function ()
          return StackExchange.using("mathjaxEditing", function ()
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          );
          );
          , "mathjax-editing");

          StackExchange.ifUsing("editor", function ()
          StackExchange.using("externalEditor", function ()
          StackExchange.using("snippets", function ()
          StackExchange.snippets.init();
          );
          );
          , "code-snippets");

          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "196"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          convertImagesToLinks: false,
          noModals: false,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );








           

          draft saved


          draft discarded


















          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f199513%2fhashmap-exercise-rust-book-ch-8%23new-answer', 'question_page');

          );

          Post as a guest



































          active

          oldest

          votes













          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes










           

          draft saved


          draft discarded


























           


          draft saved


          draft discarded














          StackExchange.ready(
          function ()
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f199513%2fhashmap-exercise-rust-book-ch-8%23new-answer', 'question_page');

          );

          Post as a guest













































































          Popular posts from this blog

          Chat program with C++ and SFML

          Function to Return a JSON Like Objects Using VBA Collections and Arrays

          Will my employers contract hold up in court?