当前位置: 首页 > article >正文

Rust 学习笔记:使用迭代器改进 minigrep

Rust 学习笔记:使用迭代器改进 minigrep

  • Rust 学习笔记:使用迭代器改进 minigrep
    • 不使用 clone,而使用迭代器
    • 使用迭代器适配器使代码更清晰
    • 在循环或迭代器之间进行选择

Rust 学习笔记:使用迭代器改进 minigrep

前情提要:https://blog.csdn.net/ProgramNovice/article/details/148192426

有了这些关于迭代器的新知识,我们可以通过使用迭代器使代码更清晰、更简洁。让我们看看迭代器如何改进 Config::build 函数和 search 函数的实现。

不使用 clone,而使用迭代器

原函数:

impl Config {pub fn build(args: &[String]) -> Result<Config, &'static str> {if args.len() < 3 {return Err("not enough arguments");}let query = args[1].clone();let file_path = args[2].clone();let ignore_case = env::var("IGNORE_CASE").is_ok();Ok(Config { query, file_path, ignore_case })}
}

有了关于迭代器的新知识,我们可以修改构建函数,使其接受迭代器的所有权作为参数,将 String 值从迭代器移到 Config 中,而不是调用 clone 并进行新的分配。

env::args 函数返回一个迭代器,类型是 std::env::Args,该类型实现了 Iterator trait 并返回 String 值。

修改代码,使得其所有权直接传递给 Config::build 函数。

fn main() {let config = Config::build(env::args()).unwrap_or_else(|err| {eprintln!("Problem parsing arguments: {err}");process::exit(1);});// --skip--
}

接下来,我们需要更新 Config::build 函数:

impl Config {pub fn build(mut args: impl Iterator<Item = String>) -> Result<Config, &'static str> {args.next();let query = match args.next() {Some(arg) => arg,None => return Err("Didn't get a query string"),};let file_path = match args.next() {Some(arg) => arg,None => return Err("Didn't get a file path"),};let ignore_case = env::var("IGNORE_CASE").is_ok();Ok(Config { query, file_path, ignore_case })}
}

我们更新了 Config::build 函数的签名,所以参数 args 有一个泛型类型,trait 约束为 impl Iterator<Item = String> 而不是 &[String],这意味着 args 可以是任何实现 Iterator trait 并返回 String 项的类型。因为我们获得了 args 的所有权我们将通过迭代来改变 args,我们可以在 args 参数的说明中添加 mut 关键字来使它可变。

使用迭代器适配器使代码更清晰

项目的 search 函数中利用了迭代器:

pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {let mut results = Vec::new();for line in contents.lines() {if line.contains(query) {results.push(line);}}results
}

我们可以使用迭代器适配器方法以更简洁的方式编写此代码。这样做还可以避免使用可变的中间结果向量。

pub fn search<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {contents.lines().filter(|line| line.contains(query)).collect()
}

函数式编程风格倾向于最小化可变状态的数量,以使代码更清晰。删除可变状态可能会使将来的增强实现并行搜索,因为我们不必管理对结果向量的并发访问。

类似的,我们修改 search_case_insensitive 函数:

pub fn search_case_insensitive<'a>(query: &str, contents: &'a str) -> Vec<&'a str> {contents.lines().filter(|line| line.to_lowercase().contains(&query.to_lowercase())).collect()
}

在循环或迭代器之间进行选择

大多数 Rust 程序员更喜欢使用迭代器风格。一开始很难掌握窍门,但是一旦了解了各种迭代器适配器及其功能,就会更容易理解迭代器。

代码没有处理循环的各个部分和构建新的向量,而是专注于循环的高级目标。这抽象掉了一些常见的代码,因此更容易看到这些代码特有的概念,例如迭代器中的每个元素必须通过的过滤条件。

http://www.lryc.cn/news/2392571.html

相关文章:

  • 多线程(5)——单例模式,阻塞队列
  • React整合【ECharts】教程004:饼图的构建和基本设置
  • 视频监控汇聚平台EasyCVR工业与安全监控:防爆摄像机的安全应用与注意事项
  • Android 倒计时总结
  • 基于 Redis 实现分布式锁:原理及注意事项
  • 手机设备多?怎样设置IP保证不关联
  • Linux 中常见的安全与权限机制
  • Golang|单例模式
  • 哈尔滨工业大学计算机系统大作业程序人生-Hello’s P2P
  • 小程序定制开发:从需求到落地,打造企业专属数字化入口
  • 【C/C++】基于 Docker 容器运行的 Kafka + C++ 练手项目
  • Linux系统管理与编程24:基础条件准备-混搭“本地+阿里云”yum源
  • 新一代Python管理UV完全使用指南|附实际体验与效果对比
  • 如何在 Windows 10 PC 上获取 iPhone短信
  • STM32程序运行不了,仿真功能也异常,连断点和复位都异常了
  • Linux 系统中的软链接与硬链接
  • Python爬虫第22节- 结合Selenium识别滑动验证码实战
  • 【C/C++】chrono简单使用场景
  • Escrcpy(安卓手机投屏软件) v1.29.6 中文绿色版
  • Oracle MOVE ONLINE 实现原理
  • Linux:深入理解网络层
  • 【设计模式】简单工厂模式,工厂模式,抽象工厂模式,单例,代理,go案例区分总结
  • Linux_编辑器Vim基本使用
  • vue展示修改前后对比,并显示修改标注diff
  • LiveWallpaperMacOS:让你的 Mac 桌面动起来
  • [预训练]Encoder-only架构的预训练任务核心机制
  • 07-后端Web实战(部门管理)
  • mysql ACID 原理
  • [Rust_1] 环境配置 | vs golang | 程序运行 | 包管理
  • 二十五、面向对象底层逻辑-SpringMVC九大组件之HandlerMapping接口设计