Skip to main content
Edited Github code URL
Source Link
philipjkim
  • 437
  • 4
  • 12
  • This code is on GitHubGitHub also.
  • I found there are similar questions related to the same quiz on Code Review, but the implementations differ. So I think they're not duplicated question.
  • This code is on GitHub also.
  • I found there are similar questions related to the same quiz on Code Review, but the implementations differ. So I think they're not duplicated question.
  • This code is on GitHub also.
  • I found there are similar questions related to the same quiz on Code Review, but the implementations differ. So I think they're not duplicated question.
Source Link
philipjkim
  • 437
  • 4
  • 12

Rust: calculating mean, median, and mode for numbers from stdin

This quiz is on The Rust Programming Language online ebook.

Given a list of integers, use a vector and return the mean (the average value), median (when sorted, the value in the middle position), and mode (the value that occurs most often; a hash map will be helpful here) of the list.

As a novice Rust programmer, I'd like get my code reviewed and learn more about programming Rust.

There are a couple of things I'd like to know:

  • getting input using io::stdin().read_line() is ok for this case,
  • if there's better looping (user-input) and quitting pattern,
  • handling user input errors with helpful error message (Your input is invalid. Please enter whitespace-separated integers.) then re-ask with prompt, instead of panicking,
  • whether type casting using as is commonly-used (ex: i32 -> f32),
  • implementation of get_median() and get_mode() can be simpler than now

Here's my code:

use std::collections::HashMap;
use std::io::{self, prelude::*};

fn main() {
    let stdin = io::stdin();

    'mainloop: loop {
        print!("Enter space-separated numbers (q for quit)> ");
        io::stdout().flush().expect("flush failed");

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

        if line == "q\n" {
            break 'mainloop;
        }

        // TODO: handling ParseIntError
        let nums: Vec<i32> = line
            .split_whitespace()
            .map(|s| s.parse::<i32>().unwrap())
            .collect();

        let mean = nums.iter().sum::<i32>() as f32 / nums.len() as f32;

        println!(
            "numbers: {:?}, mean: {}, median: {}, mode: {}",
            nums,
            mean,
            get_median(&nums),
            get_mode(&nums)
        );
    }
}

fn get_median(v: &Vec<i32>) -> f32 {
    if v.len() < 1 {
        return 0.0;
    }

    let mut vec = v.clone();
    vec.sort();
    if vec.len() % 2 == 1 {
        return *vec.get(vec.len() / 2).unwrap() as f32;
    }
    return (*vec.get(vec.len() / 2 - 1).unwrap() + *vec.get(vec.len() / 2).unwrap()) as f32 / 2.0;
}

fn get_mode(v: &Vec<i32>) -> i32 {
    let mut map = HashMap::new();
    for num in v {
        let count = map.entry(num).or_insert(0);
        *count += 1;
    }
    return **map.iter().max_by_key(|(_, v)| *v).unwrap().0;
}
  • This code is on GitHub also.
  • I found there are similar questions related to the same quiz on Code Review, but the implementations differ. So I think they're not duplicated question.