Book chapter 8 questions

I solved these questions
https://doc.rust-lang.org/book/ch08-03-hash-maps.html#summary
I just wanted you to check if there is a better way to write these codes.

fn mode(v: &Vec<i32>) -> Option<i32> {
    if v.len() == 0 {
        return None;
    }
    let mut counter = HashMap::new();
    for i in v {
        let count = counter.entry(i).or_insert(0);
        *count += 1;
    }
    let mut max = (None, None);
    for (num, count) in counter {
        if max.0 == None || count > max.1.unwrap() {
            max = (Some(*num), Some(count));
        }
    }
    max.0
}

fn median(v: &mut Vec<i32>) -> i32 {
    v.sort();
    v[v.len() / 2]
}
fn pig_latin(s: &str) -> String {
    let mut result = String::with_capacity(s.len() + 4);
    let mut chars = s.chars();
    let first = chars.next().unwrap();
    if is_vowel(first) {
        result.push_str(s);
        result.push_str("-hay");
    } else {
        result.push_str(chars.as_str());
        result.push('-');
        result.push(first);
        result.push_str("ay");
    }
    result
}

fn is_vowel(c: char) -> bool {
    c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u'
}

And I couldn't solve the last one. can someone share his answer pls

Comments, in no particular order of importance:

  • Taking &Vec is always unnecessary and actually harmful; it forces the caller to have a Vec. You should take a slice instead, so one can pass in any type that is convertible to a slice.
  • Similarly, taking a &mut Vec is useless if you don't need to insert into or delete from the vector. Take a mutable slice instead.
  • Your implementation of median() contains two errors:
    1. If the slice is empty, it panics
    2. If the slice has an even number of elements, it returns the first element of the second half instead of obeying the definition of the median (you should be returning the mean of the two middle elements).
  • In mode(), you are re-implementing Iterator::max_by_key() manually.
  • pig_latin() assumes the string is a single word. I'd think splitting the string on whitespace was meant to be part of the task.
  • is_vowel() is better expressed as ['a', 'e', 'i', 'o', 'u'].contains(&c).
  • A bunch of repeated push_str() are better expressed as write!() and a format string.

Overall, here are my solutions.

5 Likes

I think sorting is the solution that the book expected when that part was written, but note that there's now select_nth_unstable which can be used to get the median in a better complexity class compared to fully sorting the whole slice.

4 Likes

Thanks for your help guys.
can you check this last question too

use std::collections::HashMap;
use std::io::{self, Write};

#[derive(Debug)]
struct Employee {
    name: String,
}

fn main() {
    let mut company = HashMap::<String, Vec<Employee>>::new();
    loop {
        let mut cmd = String::new();
        print!("Command: ");
        io::stdout().flush().unwrap();
        io::stdin().read_line(&mut cmd).unwrap();
        let words: Vec<&str> = cmd.split_whitespace().collect();
        if words.len() > 0 && words[0] == "Add" {
            if words.len() != 4 {
                println!("Wrong command");
                continue;
            }
            company
                .entry(words[3].to_string())
                .or_insert(Vec::<Employee>::new())
                .push(Employee {
                    name: words[1].to_string(),
                });
        }
        println!("{:?}", company);
    }
}

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.