made it a little more rust idiomatic

This commit is contained in:
2026-05-13 17:48:29 -04:00
parent b33cc21882
commit 0f5c6610e6
+27 -30
View File
@@ -37,15 +37,16 @@ pub fn tokenize(input: &str) -> Vec<String> {
// Since our tokenize function returns new Strings, there is not much sense in // Since our tokenize function returns new Strings, there is not much sense in
// taking &[&str] here since this would require an extra allocation to move the // taking &[&str] here since this would require an extra allocation to move the
// string slices to a new vector. This doesn't copy heap on the way in anyway. // string slices to a new vector. This doesn't copy heap on the way in anyway.
pub fn create_frequency_vec(input: &mut [String]) -> Vec<(String,usize)> { pub fn create_frequency_vec(input: &[String]) -> Vec<(String,usize)> {
// save a copy on the way in by allowing mutation of the passed input // perhaps unnecessary copy, but this preserves the original token list
input.sort(); // O(n log n) let mut sorted = input.to_vec();
sorted.sort(); // O(n log n)
let mut counts : Vec<(String, usize)> = Vec::new(); let mut counts : Vec<(String, usize)> = Vec::new();
for w in input { // O(n) for w in sorted { // O(n)
match counts.last_mut() { match counts.last_mut() {
Some((last, count)) if last == w => *count += 1, Some((last, count)) if last == &w => *count += 1,
_ => counts.push((w.to_string(), 1)), _ => counts.push((w.clone(), 1)),
} }
} }
counts.sort_by(|a,b| b.1.cmp(&a.1)); // sort by frequency, O(m log m) counts.sort_by(|a,b| b.1.cmp(&a.1)); // sort by frequency, O(m log m)
@@ -53,9 +54,7 @@ pub fn create_frequency_vec(input: &mut [String]) -> Vec<(String,usize)> {
} }
pub fn analyze_word_count(input: &[(String,usize)]) -> usize { pub fn analyze_word_count(input: &[(String,usize)]) -> usize {
let mut count = 0; input.iter().map(|(_,c)| c).sum()
input.iter().for_each(|(_,c)| { count+=c });
count
} }
pub fn analyze_unique_word_count(input: &[(String,usize)]) -> usize { pub fn analyze_unique_word_count(input: &[(String,usize)]) -> usize {
@@ -64,7 +63,7 @@ pub fn analyze_unique_word_count(input: &[(String,usize)]) -> usize {
pub fn average_word_length(input: &[(String, usize)]) -> f64 { pub fn average_word_length(input: &[(String, usize)]) -> f64 {
if input.is_empty() { if input.is_empty() {
return 0 as f64; return 0.0;
} }
let mut len = 0; let mut len = 0;
let mut tokens = 0; let mut tokens = 0;
@@ -86,9 +85,7 @@ pub fn top_n_most_used(input: &[(String, usize)], n: usize) -> &[(String, usize)
// todo: option // todo: option
pub fn longest_word(input: &[(String, usize)]) -> usize { pub fn longest_word(input: &[(String, usize)]) -> usize {
let mut max = 0; input.iter().map(|(w,_)| w.len()).max().unwrap_or(0)
input.iter().for_each(|(w,_)| if w.len() > max { max = w.len() });
max
} }
pub fn num_digits(n: usize) -> usize { pub fn num_digits(n: usize) -> usize {
@@ -119,7 +116,7 @@ pub fn print_analysis(input: &[(String, usize)]) {
println!("{:<col1$} {:<col2$} {:<col3$}", "Word", "Count", "%_of_total"); println!("{:<col1$} {:<col2$} {:<col3$}", "Word", "Count", "%_of_total");
println!("{:-<end$}", ""); println!("{:-<end$}", "");
for (w, c) in counts { for (w, c) in counts {
println!("{:<col1$} {:<col2$} {:<col3$.2}%", w, c, (*c as f64/(wc as f64) * 100 as f64)); println!("{:<col1$} {:<col2$} {:<col3$.2}%", w, c, (*c as f64/(wc as f64) * 100.0));
} }
} }
@@ -130,8 +127,8 @@ fn main() {
} }
pub fn test_print() { pub fn test_print() {
let mut tokens = tokenize("Hellow, wod! hello hello hello ok bye then oa more plz"); let tokens = tokenize("Hellow, wod! hello hello hello ok bye then oa more plz");
let freq_vec = create_frequency_vec(&mut tokens); let freq_vec = create_frequency_vec(&tokens);
print_analysis(&freq_vec); print_analysis(&freq_vec);
} }
@@ -140,11 +137,11 @@ pub mod test {
use super::*; use super::*;
#[test] #[test]
pub fn empty() { fn empty() {
let mut tokens = tokenize(""); let tokens = tokenize("");
assert_eq!(tokens.len(), 0); assert_eq!(tokens.len(), 0);
let freq_vec = create_frequency_vec(&mut tokens); let freq_vec = create_frequency_vec(&tokens);
assert_eq!(freq_vec.len(), 0); assert_eq!(freq_vec.len(), 0);
let wc = analyze_word_count(&freq_vec); let wc = analyze_word_count(&freq_vec);
@@ -154,7 +151,7 @@ pub mod test {
assert_eq!(uwc, 0); assert_eq!(uwc, 0);
let avg_len = average_word_length(&freq_vec); let avg_len = average_word_length(&freq_vec);
assert_eq!(avg_len, 0 as f64); assert_eq!(avg_len, 0.0);
let top_n = top_n_most_used(&freq_vec, 4); let top_n = top_n_most_used(&freq_vec, 4);
assert_eq!(top_n.len(), 0); assert_eq!(top_n.len(), 0);
@@ -163,11 +160,11 @@ pub mod test {
} }
#[test] #[test]
pub fn basic() { fn basic() {
let mut tokens = tokenize("Hello, world! hello"); let tokens = tokenize("Hello, world! hello");
assert_eq!(tokens.len(), 3); assert_eq!(tokens.len(), 3);
let freq_vec = create_frequency_vec(&mut tokens); let freq_vec = create_frequency_vec(&tokens);
assert_eq!(freq_vec.len(), 2); assert_eq!(freq_vec.len(), 2);
let wc = analyze_word_count(&freq_vec); let wc = analyze_word_count(&freq_vec);
@@ -177,7 +174,7 @@ pub mod test {
assert_eq!(uwc, 2); assert_eq!(uwc, 2);
let avg_len = average_word_length(&freq_vec); let avg_len = average_word_length(&freq_vec);
assert_eq!(avg_len, 5 as f64); assert_eq!(avg_len, 5.0);
let top_n = top_n_most_used(&freq_vec, 4); let top_n = top_n_most_used(&freq_vec, 4);
assert_eq!(top_n[0].0, "hello"); assert_eq!(top_n[0].0, "hello");
@@ -186,11 +183,11 @@ pub mod test {
} }
#[test] #[test]
pub fn unicode_and_ctrl() { fn unicode_and_ctrl() {
let mut tokens = tokenize("Hello\u{0000} world! hello ß"); let tokens = tokenize("Hello\u{0000} world! hello ß");
assert_eq!(tokens.len(), 4); assert_eq!(tokens.len(), 4);
let freq_vec = create_frequency_vec(&mut tokens); let freq_vec = create_frequency_vec(&tokens);
assert_eq!(freq_vec.len(), 4); assert_eq!(freq_vec.len(), 4);
let wc = analyze_word_count(&freq_vec); let wc = analyze_word_count(&freq_vec);
@@ -209,11 +206,11 @@ pub mod test {
} }
#[test] #[test]
pub fn unicode_2() { fn unicode_2() {
let mut tokens = tokenize("café"); let tokens = tokenize("café");
assert_eq!(tokens.len(), 1); assert_eq!(tokens.len(), 1);
let freq_vec = create_frequency_vec(&mut tokens); let freq_vec = create_frequency_vec(&tokens);
assert_eq!(freq_vec.len(), 1); assert_eq!(freq_vec.len(), 1);
let wc = analyze_word_count(&freq_vec); let wc = analyze_word_count(&freq_vec);