Rust 学习笔记:迭代器

Rust 学习笔记:迭代器

  • Rust 学习笔记:迭代器
    • Iterator trait 和 next 方法
    • 使用迭代器的方法
    • 生成其他迭代器的方法
    • 使用闭包捕获它们的环境

Rust 学习笔记:迭代器

在 Rust 中,迭代器负责遍历每个项的逻辑。迭代器是懒惰的,这意味着它们在调用消耗迭代器的方法之前没有作用。

示例:

    let v1 = vec![1, 2, 3];let v1_iter = v1.iter();for val in v1_iter {println!("Got: {val}");}

在这个示例中,我们将迭代器的创建与在 for 循环中使用迭代器分开。当使用 v1_iter 中的迭代器调用 for 循环时,迭代器中的每个元素都会在循环的一次迭代中使用,并打印出每个值。

Iterator trait 和 next 方法

所有迭代器都实现一个名为 Iterator 的 trait,该 trait 在标准库中定义。这个特性的定义是这样的:

pub trait Iterator {type Item;fn next(&mut self) -> Option<Self::Item>;// methods with default implementations elided
}

注意,这个定义使用了一些新的语法:type Item 和 Self::Item,它们定义了与这个 trait 相关联的类型。这段代码表明,实现 Iterator trait 还需要定义一个 Item 类型,并且该 Item 类型用于下一个方法的返回类型。换句话说,Item 类型将是迭代器返回的类型。

Iterator trait 只需要实现者定义一个方法:next 方法,每次返回迭代器的一个项,包装在 Some 中,迭代结束时返回 None。

我们可以直接在迭代器上调用 next 方法。下面的代码演示了在 vector 创建的迭代器上重复调用 next 会返回哪些值。

    #[test]fn iterator_demonstration() {let v1 = vec![1, 2, 3];let mut v1_iter = v1.iter();assert_eq!(v1_iter.next(), Some(&1));assert_eq!(v1_iter.next(), Some(&2));assert_eq!(v1_iter.next(), Some(&3));assert_eq!(v1_iter.next(), None);}

注意,我们需要将 v1_iter 设置为可变的:在迭代器上调用 next 方法会改变迭代器用于跟踪其在序列中的位置的内部状态,每次调用都会消耗迭代器中的一个项。

在使用 for 循环时,不需要将 v1_iter 设为可变的,因为循环在后台获取了 v1_iter 的所有权并使其可变。

还要注意,从调用 next 得到的值是对 vector 中值的不可变引用。iter 方法在不可变引用上生成一个迭代器。如果要创建一个接受 v1 的所有权并返回拥有的值的迭代器,可以调用 into_iter 方法。类似地,如果要在可变引用上迭代,可以调用 iter_mut 方法。

使用迭代器的方法

Iterator trait 有许多不同的方法,由标准库提供默认实现。其中一些方法在其定义中调用 next 方法,这就是为什么在实现 Iterator trait 时需要实现 next 方法的原因。

调用 next 的方法称为消费适配器,因为调用它们会耗尽迭代器。

一个例子是 sum 方法,它获得迭代器的所有权,并通过重复调用 next 来遍历项,从而消耗迭代器。当它遍历时,它将每个项目添加到运行总数中,并在迭代完成时返回总数。

    #[test]fn iterator_sum() {let v1 = vec![1, 2, 3];let v1_iter = v1.iter();let total: i32 = v1_iter.sum();assert_eq!(total, 6);}

注意,在调用 sum 之后不允许使用 v1_iter,因为 sum 将获得调用它的迭代器的所有权。

生成其他迭代器的方法

迭代器适配器是在 Iterator trait 上定义的不消耗迭代器的方法。相反,它们通过改变原始迭代器的某些方面来生成不同的迭代器。

下面代码是调用迭代器适配器方法 map 的示例,该方法接受一个闭包,在遍历每个项目时调用该闭包。map 方法返回一个新的迭代器,用于生成修改后的项。

    let v1: Vec<i32> = vec![1, 2, 3];v1.iter().map(|x| x + 1);

运行代码会得到一个警告:我们指定的闭包永远不会被调用。这个警告提醒了我们原因:迭代器适配器是惰性的,我们需要在这里消费迭代器。

在这里插入图片描述

为了修复这个警告并消费迭代器,我们将使用 collect 方法,此方法使用迭代器并将结果值收集到集合数据类型中。

    let v1: Vec<i32> = vec![1, 2, 3];let v2: Vec<_> = v1.iter().map(|x| x + 1).collect();assert_eq!(v2, vec![2, 3, 4]);

因为 map 接受闭包,所以可以指定想对每个项执行的任何操作。

还可以将多个调用链接到迭代器适配器,以可读的方式执行复杂的操作。但是,由于所有迭代器都是惰性的,因此必须调用一个使用适配器的方法来从调用迭代器适配器中获取结果。

使用闭包捕获它们的环境

许多迭代器适配器将闭包作为参数,通常我们指定作为迭代器适配器参数的闭包将是捕获其环境的闭包。

示例:

#[derive(PartialEq, Debug)]
struct Shoe {size: u32,style: String,
}fn shoes_in_size(shoes: Vec<Shoe>, shoe_size: u32) -> Vec<Shoe> {shoes.into_iter().filter(|s| s.size == shoe_size).collect()
}#[cfg(test)]
mod tests {use super::*;#[test]fn filters_by_size() {let shoes = vec![Shoe {size: 10,style: String::from("sneaker"),},Shoe {size: 13,style: String::from("sandal"),},Shoe {size: 10,style: String::from("boot"),},];let in_my_size = shoes_in_size(shoes, 10);assert_eq!(in_my_size,vec![Shoe {size: 10,style: String::from("sneaker")},Shoe {size: 10,style: String::from("boot")},]);}
}

对于本例,我们将使用接受闭包的 filter 方法。闭包从迭代器获取一个元素并返回 bool 值。如果闭包返回 true,则该值将包含在 filter 生成的迭代器中。如果闭包返回 false,则不包含该值。

在 shoes_in_size 的函数体中,调用 into_iter 来创建一个接受 vector 对象所有权的迭代器。然后调用 filter 将该迭代器改编为一个新的迭代器。filter 方法的闭包从环境中捕获 shoe_size 参数,并将其值与每只鞋的尺寸进行比较,只保留指定尺寸的鞋子。最后,调用 collect 将经过调整的迭代器返回的值收集到函数返回的向量中。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/web/81774.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【深度剖析】义齿定制行业数字化转型模式创新研究(上篇2:痛点和难点分析)

数字化转型正在重塑义齿行业的生态格局,但也面临技术融合与模式变革的深层挑战。当前,义齿定制行业正处于从传统手工制造向全流程数字化制造转型的关键阶段。3D扫描、CAD/CAM(计算机辅助设计与制造)、3D打印等技术的广泛应用,显著提升了义齿制作的精度和效率。传统石膏模型…

window安装nginx

步骤1&#xff1a;下载Nginx for Windows​ 访问Nginx官网下载页面&#xff1a;https://nginx.org/en/download.html 在​​Stable version​​&#xff08;稳定版&#xff09;下找到Windows版本&#xff0c;点击下载.zip文件&#xff08;如 nginx-1.28.0.zip&#xff09; 步…

气象算法工程师学习路径

目录 &#x1f324;️ 气象学与数值预报基础课程&#x1f916; 气象人工智能与数据分析课程&#x1f4d8; 进阶与实战课程推荐&#x1f9ed; 学习建议与路径规划 如果希望成为一名气象算法工程师&#xff0c;并寻找深入浅出、理论与实践结合的学习资源&#xff0c;以下是为你精…

回调函数的理解

int yuxiangrousi 0; // 全局变量&#xff1a;鱼香肉丝&#xff08;酱油量&#xff09;// 回调函数&#xff1a;妈妈处理酱油&#xff08;将酱油加入鱼香肉丝&#xff09; void mother_callback(int new_jiangyou) {yuxiangrousi new_jiangyou; // 把酱油放进鱼香肉丝 }// 孩…

多部手机连接同一wifi的ip一样吗?如何更改ip

通常情况下&#xff0c;多部手机连接同一个WiFi时&#xff0c;它们的IP地址是各不相同的&#xff08;在局域网内&#xff09;。但是&#xff0c;从互联网&#xff08;外网&#xff09;的角度看&#xff0c;它们共享同一个公网IP地址。让我详细解释一下&#xff0c;并说明如何更…

环境温度通过H2A.Zub和H3K27me3动态调控拟南芥细胞命运决定

2025年4月22日&#xff0c;中国科学院遗传与发育生物学研究所肖军研究组在Developmental Cell在线发表了题为Dynamic control of H2A.Zub and H3K27me3 by ambient temperature during cell fate determination in Arabidopsis的研究论文&#xff0c;本研究综合运用ChIP-seq、C…

2024 吉林 CCPC

文章目录 2024 吉林 CCPCL. Recharge&#xff08;思维、分配&#xff09;G. Platform Game(模拟)E. Connect Components (排序、思维)D. Parallel Lines 2024 吉林 CCPC 题目链接&#xff1a; Dashboard - The 2024 CCPC National Invitational Contest (Changchun) , The 17…

day13 leetcode-hot100-24(链表3)

234. 回文链表 - 力扣&#xff08;LeetCode&#xff09; 1.转化法 思路 将链表转化为列表进行比较 复习到的知识 arraylist的长度函数&#xff1a;list.size() 具体代码 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode ne…

Vim文本编辑器快捷键用法以及简单介绍

目录 vim文本编辑器 简介&#xff1a; 语法&#xff1a; vim模式介绍&#xff1a; 模式切换&#xff1a; 用法&#xff1a; 编辑模式&#xff1a; 一般模式&#xff1a; 命令模式&#xff1a; vim文本编辑器 简介&#xff1a; 在命令行界面下&#xff0c;最常用的文本…

从 0 到 1:Spring Boot 与 Spring AI 深度实战(基于深度求索 DeepSeek)

在人工智能技术与企业级开发深度融合的今天&#xff0c;传统软件开发模式与 AI 工程化开发的差异日益显著。作为 Spring 生态体系中专注于 AI 工程化的核心框架&#xff0c;Spring AI通过标准化集成方案大幅降低 AI 应用开发门槛。本文将以国产大模型代表 ** 深度求索&#xff…

[Windows] 摸鱼小工具:隐藏软件(重制版)

由吾爱大神写的摸鱼工具&#xff1a; 数据存放路径为C:\Users\用户名\AppData\Local\HideSoft&#xff0c;如果不想用时&#xff0c;删除软件及此路径下的HideSoft文件夹。如添加了开机启动&#xff0c;删除启动菜单文件夹的快捷方式即可&#xff0c;或者删除前在软件中取消设置…

C++ 判断文件的编码类型

大多数文本编辑器&#xff0c;都会在文本文件的头部插入一部分特殊的字节&#xff0c;用于辅助文本编辑器来判断该文件的字符集编码类型。 如&#xff1a;记事本 目前支持的字符集类型&#xff0c;通常为三种&#xff1a; Unicode、UTF8、UnicodeBIG、CP_ACP&#xff08;默认…

时间序列噪声模型分析软件推荐与使用经验

最近在论文大修2024年投稿的一篇文章&#xff0c;大修了2轮&#xff0c;最后一次还是重新投稿&#xff0c;其中有一个问题一直被审稿人怼&#xff0c;他认为我计算时间序列的趋势的时候&#xff0c;没有考虑时间的相关性&#xff0c;即对噪声模型的估计不合理&#xff0c;会影响…

【redis实战篇】第六天

摘要&#xff1a; 本文介绍了基于Redis的秒杀系统优化方案&#xff0c;主要包含两部分&#xff1a;1&#xff09;通过Lua脚本校验用户秒杀资格&#xff0c;结合Java异步处理订单提升性能&#xff1b;2&#xff09;使用Redis Stream实现消息队列处理订单。方案采用Lua脚本保证库…

【Java Web】速通HTML

参考笔记: JavaWeb 速通HTML_java html页面-CSDN博客 目录 一、前言 1.网页组成 1 结构 2 表现 3 行为 2.HTML入门 1 基本介绍 2 基本结构 3. HTML标签 1 基本说明 2 注意事项 4. HTML概念名词解释 二、HTML常用标签汇总 + 案例演示 1. 字体标签 font (1)定义 (2)案例 2…

Oracle/openGauss中,DATE/TIMESTAMP与数字日期/字符日期比较

ORACLE 运行环境 openGauss 运行环境 0、前置知识 ORACLE&#xff1a;DUMP()函数用于返回指定表达式的数据类型、字节长度及内部存储表示的详细信息 SELECT DUMP(123) FROM DUAL; -- Typ2 Len3: 194,2,24 SELECT DUMP(123) FROM DUAL;-- Typ96 Len3: 49,50,51 -- ASCII值&am…

[学习]C++ 模板探讨(代码示例)

C 模板探讨 文章目录 C 模板探讨一、模板基础概念二、函数模板三、类模板1. 类模板的定义与使用2. 成员函数模板3. 类模板的静态成员与继承 四、模板进阶特性1. 非类型模板参数2. 可变参数模板&#xff08;Variadic Templates&#xff09;3. 模板元编程&#xff08;TMP&#xf…

人工智能-训练AI模型涉及多个步骤

训练AI模型涉及多个步骤&#xff0c;包括数据预处理、选择合适的模型、训练模型以及评估模型性能。下面是一个详细的流程&#xff0c;以常见的机器学习任务——分类问题为例&#xff0c;展示如何使用Python中的scikit-learn库来训练一个简单的AI模型。 步骤 1: 导入所需的库 …

LVS+Keepalived 高可用

目录 一、核心概念 1. LVS&#xff08;Linux Virtual Server&#xff09; 2. Keepalived 二、高可用架构设计 1. 架构拓扑图 2. 工作流程 三、部署步骤&#xff08;以 DR 模式为例&#xff09; 1. 环境准备 2. 主 LVS 节点配置 &#xff08;1&#xff09;安装 Keepali…

TCP 三次握手过程详解

TCP 三次握手过程详解 一、TCP握手基础概念 1.1 什么是TCP握手 TCP三次握手是传输控制协议(Transmission Control Protocol)在建立连接时的标准过程,目的是确保通信双方具备可靠的双向通信能力。 关键结论:三次握手的本质是通过序列号同步和能力协商建立可靠的逻辑连接。 …