问题描述

测试代码

解决思路

代码实现

代码解析

第一部分: 命令行操作和文件读取

第二部分: 单词统计

第三部分: 排序和Top N

第四部分: 打印直方图

总结

实现一个统计单词词频的小程序(rust入门课程)

小葵

2024-07-04

🏷

rust面试题

问题描述

实现一个统计单词词频、支持Top N排序显示,并根据出现频率打印直方图的命令行工具

  • 读取文件内容:读取指定文件的内容。
  • 统计单词词频:将文件内容分割成单词,并统计每个单词出现的次数。
  • 排序并获取Top N:根据单词出现的频率进行排序,并获取前N个结果。
  • 打印直方图:根据每个单词的词频打印直方图。

这次我们要用rust实现一个wordcount统计词频的工具,学习rust的文件操作、HashMap和各种容器的转换。

Rust是当前编程语言的当红炸子鸡,它的内存安全和并发性能是其他语言无法比拟的,但是rust的门槛极高,学习曲线陡峭

所以我们需要通过实际的项目来学习rust。

测试代码

  #[test]
  fn test_count_words() {
      let content = "Hello, world! Hello, world!";
      let word_count = count_words(content);
      assert_eq!(word_count.get("Hello"), Some(&2));
      assert_eq!(word_count.get("world"), Some(&2));
  }
  #[test]
  fn test_count_words_with_punctuation() {
      let content = "Hello, world! Hello,    world!";
      let word_count = count_words(content);
      assert_eq!(word_count.get("Hello"), Some(&2));
      assert_eq!(word_count.get("world"), Some(&2));
  }
  #[test]
  fn test_count_words_with_newline() {
      let content = "Hello, world!\t\r\nHello, world!";
      let word_count = count_words(content);
      assert_eq!(word_count.len(), 2);
      assert_eq!(word_count.get("Hello"), Some(&2));
      assert_eq!(word_count.get("world"), Some(&2));
  }

解决思路

这个程序不涉及到复杂的算法,思路和题目描述一样,主要是学习rust的文件操作、HashMap和各种容器的转换。

  1. 可以通过std::fs 读取文件内容,然后通过split_whitespace来分割单词
  2. 使用HashMap来统计单词的词频, HashMap是rust的标准库,可以直接使用
  3. HashMap转换成Vec,然后排序获取Top N
  4. 打印直方图,因为直方图是一个比例图表,所以需要先计算出最大值,然后根据比例来打印

代码实现

完整代码请参考: wordcount.rs

代码解析

我们讲一下代码的实现:

第一部分: 命令行操作和文件读取

  • 3-13 行: 通过env::args()获取命令行参数
  • 9-12 行: top_n这个参数是一个Option类型,如果没有传入参数,就初始化一个默认值,如果参数输入不是int,也没关系,我们通过unwrap_or来得到一个默认值而不是panic
  • 15行: 读出文件到一个String

第二部分: 单词统计

  • 27行: 初始化了一个HashMap,用来存储单词和词频, 因为rust会根据上下文推导类型,虽然HashMap是一个范型容器,但是初始化的时候,并不需要我们声明类型,这样会方便很多
  • 29-35行: 通过split_whitespace来分割单词,然后通过entry来插入或者更新HashMap中的值, entryHashMap的一个方法,如果key存在,就返回一个Entry,如果key不存在,就插入一个key,然后返回一个Entry, 这个写法是兼顾性能的,也就是说,如果key存在,就不会重复查找key,直接更新value

第三部分: 排序和Top N

  • 21-22行: 将HashMap转换成Vec,然后通过sort_by来排序

因为我们要根据词频来排序,所以我们需要一个比较函数,这个比较函数是一个闭包,我们通过|a, b|来定义一个闭包,然后通过cmp来比较两个值

第四部分: 打印直方图

  • 42行: 取得第一个的词频,这个词频就是最大值
  • 44-52行: 打印直方图,通过take(top_n)来获取前N个单词,然后通过iter()来遍历
  • 46-50行: 根据题目要求要做一个直方图的比例换算,如果最大的都没超过10个,那么就不需要修改比例,否则就需要修改比例,这样显示就不会出现一个单词上万次,然后打印出上万个*的情况

总结

这个题目主要是学习rust的文件操作、HashMap和各种容器的转换

Rust的写法特别严谨,和C++比较像,特别是容器和范型方面都是和C++类似的

虽然我们的题目要求比较简单,但是我们写代码的时候要考虑各种异常情况,比如文件不存在,文件读取失败,参数输入错误等等

最后我们在显示的时候,如果做一个简单的比例换算,就可以让显示效果变得很优雅,那么这种细节就对你工作特别有帮助

rust是后端的新宠,学习曲线陡峭,但是只要你坚持下去,你会发现rust的内存安全和并发性能是其他语言无法比拟的

所有的后端面试常见的问题,我们每天都会在我们的编程群里面讨论和Code review, 欢迎大家加入我们的编程群,一起学习和进步。

编程交流群

欢迎大家关注 入职啦 (公众号: ruzhila) ,获取更多有趣的编程挑战题和技术干货!

友情链接:

Copyright© 2024 杭州园中葵科技有限公司 版权所有