Rust学习之实现命令行小工具minigrep(二)

农民  论坛元老 | 2025-4-18 20:12:27 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 1578|帖子 1578|积分 4734

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
Rust学习之实现命令行小工具minigrep(二)

Rust学习之实现命令行小工具minigrep(一)
前言

继承记载一下Rust 语言学习过程,上次写了一个命令行查找字符串的小项目minigrep。学习完了闭包(Closures)和迭代器(Iterators)之后,我们使用这两个技能来改进minigrep这个项目。
本文源码:代码堆栈
改进实现

在minigrep1 这个项目中,lib.rs文件,我们对Config的build方法中进行改进。
上次我们的代码如下:
  1. pub struct Config {
  2.     pub query: String,
  3.     pub file_path: String,
  4.     pub ignore_case: bool,
  5. }
  6. impl Config {
  7.     pub fn build(args: &[String]) -> Result<Config, &'static str> { // 1
  8.         if args.len() < 3 {
  9.             return Err("Not enouth arguments"); // 传入参数不够
  10.         }
  11.         let query = args[1].clone();
  12.         let file_path = args[2].clone();
  13.         let ignore_case = env::var("IGNORE_CASE=1").is_ok();
  14.         Ok(Config {
  15.             query,
  16.             file_path,
  17.             ignore_case
  18.         })
  19.     }
  20. }
复制代码
代码里args: &[String] 表示传进来的是字符串的切片引用,而后面的Config 须要拥有query,file_path 以及ignore_case。所以在代码中不得不克隆一份。
改进build方法

现在可以使用迭代器(Iterators)代替&[String],对这里build方法进行改进,改进步骤如下:

  • 直接将env::args() 传入 Config::build 方法,env::args() 返回一个Iterator
  • build 方法声明中,args 参数类型改为impl Iterator<Item = String>
  • 使用迭代器的next方法获取元素并使用match语法进行匹配
main.rs
  1. use std::env;
  2. use std::process;
  3. use minigrep1::Config;
  4. fn main() {
  5.     let args: Vec<String> = env::args().collect();
  6.     // dbg!(args); // stderr
  7.     // 传入两个参数
  8.     // &args 改为 env::args()
  9.     let config = Config::build(env::args()).unwrap_or_else(|err| {
  10.         eprintln!("Problem parsing arguments: {}", err);
  11.         process::exit(1);
  12.     });
  13.     if let Err(e) = minigrep1::run(config) {
  14.         eprintln!("Application error {}", e);
  15.         process::exit(1)
  16.     }
  17. }
复制代码
lib.rs
改进前:
  1. pub fn build(args: &Vec<String>) -> Result<Config, &'static str> {
  2.     if args.len() < 3 {
  3.       return Err("Not enouth arguments"); // 传入参数不够
  4.     }
  5.     let query = args[1].clone();
  6.     let file_path = args[2].clone();
  7. }
复制代码
改进后:
  1. impl Config {
  2.     pub fn build(mut args: impl Iterator<Item = String>) -> Result<Config, &'static str> {
  3.         args.next(); // skip the first argument
  4.         let query = match args.next() {
  5.             Some(arg) => arg,
  6.             None => return Err("Didn't get a query string"),
  7.         };
  8.         let file_path = match args.next() {
  9.             Some(arg) => arg,
  10.             None => return Err("Didn't get a file_path string"),
  11.         };
  12.         let ignore_case = env::var("IGNORE_CASE=1").is_ok();
  13.         Ok(Config {
  14.             query,
  15.             file_path,
  16.             ignore_case
  17.         })
  18.     }
  19. }
复制代码
改进search方法

search方法中,是对文本进行遍历,进行判定查找。这里可以用迭代器,还可以用闭包。contents.lines() 返回一个迭代器
用迭代器把之前的for 循环都替换掉,使用filter时使用闭包
  1. pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
  2.     contents
  3.         .lines()
  4.         .filter(|line| line.contains(query))
  5.         .collect()
  6. }
复制代码
同理,search_case_insensitive方法也同样使用迭代器和闭包进行修改
改进前:
  1. pub fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
  2.     let mut result = Vec::new();
  3.     let query = query.to_lowercase();
  4.     for line in contents.lines() {
  5.         if line.to_lowercase().contains(&query) {
  6.             result.push(line);
  7.         }
  8.     }
  9.     result
  10. }
复制代码
改进后:
  1. pub fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {
  2.     let query: String = query.to_lowercase();
  3.     contents.lines().filter(|line| line.to_lowercase().contains(&query)).collect()
  4. }
复制代码
总结

项目使用迭代器和闭包优化之后首先代码效率提高了,为了将引用切片转移到Config中须要使用斲丧性能的clone方法,现在我们就不须要了。迭代器迭代适配器filter 方法的使用让我们编写更加简明的代码。


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

农民

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表