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

rust迭代器

迭代器用来遍历容器。
迭代器就是把容器中的所有元素按照顺序一个接一个的传递给处理逻辑。

Rust中的迭代器
标准库中定义了Iterator特性

trait Iterator {type Item;fn next(&mut self) -> Option<Self::Item>;
}

实现了Iterator特性的结构体就是迭代器。
很多类型都有iter()方法,返回一个Iter结构体,该结构体实现了Iterator特性。

一、创建迭代器

Rust中有三种类型的迭代器。
从容器创建迭代器有三种方法。
iter() 返回一个只读可重入迭代器,迭代器元素的类型为 &T
iter_mut() 返回一个可写可重入迭代器,迭代器元素的类型为 &mut T
into_iter() 返回一个只读不可重入迭代器,迭代器元素的类型为 T

(一)iter()
返回一个只读可重入迭代器,迭代器元素的类型为&T。

例子

fn main() {let names = vec!["简单教程", "简明教程", "简单编程"];let name = names.iter();println!("{:?}", names);
}

(二)iter_mut()
返回一个可写可重入迭代器,迭代器元素的类型为&mut T。

例子

fn main() {let mut names = vec!["简单教程", "简明教程", "简单编程"];let name = names.iter_mut();println!("{:?}", names);
}

(三)into_iter()
返回一个只读不可重入迭代器,迭代器元素的类型为T
它会把容器的值移动到迭代器中。
iter_into()之后的容器不可重用。

例子

fn main() {let mut names = vec!["简单教程", "简明教程", "简单编程"];let name = names.into_iter();println!("{:?}", name);//println!("{:?}", names);//去掉注释会编译错误
}

二、使用迭代器

(一)返回迭代器元素个数
count()
消耗迭代器,计算迭代次数并返回它。
此方法将反复调用next(),直到遇到None,并返回它看到Some的次数。 请注意,即使迭代器没有任何元素,也必须至少调用一次next()
溢出行为
该方法无法防止溢出,因此对具有超过usize::MAX个元素的迭代器的元素进行计数会产生错误的结果或panics。
如果启用了调试断言,则将保证panic。
Panics
如果迭代器具有多个usize::MAX元素,则此函数可能为panic。
例子

let a = [1, 2, 3];
assert_eq!(a.iter().count(), 3);

(二)访问迭代器元素
nth(n)
返回迭代器的第n个元素。
计数从零开始,因此nth(0) 返回第一个值,nth(1) 返回第二个值,依此类推。
请注意,所有先前的元素以及返回的元素都将从迭代器中消耗。这意味着前面的元素将被丢弃,并且在同一迭代器上多次调用nth(0)将返回不同的元素。
如果n大于或等于迭代器的长度,则nth()将返回None。
例子

let a = [1, 2, 3];
assert_eq!(a.iter().nth(1), Some(&2));
多次调用nth() 不会回退迭代器:
let a = [1, 2, 3];
let mut iter = a.iter();
assert_eq!(iter.nth(1), Some(&2));
assert_eq!(iter.nth(1), None);
如果n大于或等于迭代器的长度,则返回None:
let a = [1, 2, 3];
assert_eq!(a.iter().nth(10), None);

last()
消耗迭代器,返回最后一个元素。
此方法将评估迭代器,直到返回None。 这样做时,它会跟踪当前元素。 返回None之后,last() 将返回它看到的最后一个元素。
例子

let a = [1, 2, 3];
assert_eq!(a.iter().last(), Some(&3));

(三)遍历迭代器
1.使用next()方法遍历容器
例子

fn main() {let a = [10,20,30];let mut iter = a.iter(); // 从一个数组中返回迭代器println!("{:?}",iter);//使用next() 方法返回迭代器中的下一个元素println!("{:?}",iter.next());println!("{:?}",iter.next());println!("{:?}",iter.next());println!("{:?}",iter.next());
}
编译运行结果如下
Iter([10, 20, 30])
Some(10)
Some(20)
Some(30)
None

2.使用for循环遍历
手动调用next()太麻烦了,推荐使用for循环来使用迭代器。

(1)iter()
例子

fn main() {let names = vec!["简单教程", "简明教程", "简单编程"];for name in names.iter() {println!("{}", name);}println!("{:?}", names);
}

for name in &names
实际上等价于
for name in names.iter()

(2)iter_mut()
例子

fn main() {let mut names = vec!["简单教程", "简明教程", "简单编程"];for name in names.iter_mut() {println!("{}", name);}println!("{:?}", names);
}

for name in &mut names
实际上等价于
for name in names.iter_mut()

(3)into_iter()
例子

fn main() {let names = vec!["简单教程", "简明教程", "简单编程"];for name in names.into_iter() {println!("{}", name);}//println!("{:?}", names);     //去掉注释会编译错误
}

for name in names
实际上等价于
for name in names.into_iter()

(四)迭代器转换成容器
collect()
将迭代器转换为容器。
使用collect()的最基本模式是将一个容器转换为另一个容器。 在一个容器上调用iter,进行了一堆转换,最后调用collect()。
由于collect()非常通用,因此可能导致类型推断问题。 因此,要指定类型或使用turbofish语法。
例子

let a = [1, 2, 3];
let doubled: Vec<i32> = a.iter().map(|&x| x * 2).collect();
assert_eq!(vec![2, 4, 6], doubled);
使用自动推断类型
let a = [1, 2, 3];
let doubled: Vec<_> = a.iter().map(|&x| x * 2).collect();
assert_eq!(vec![2, 4, 6], doubled);
使用turbofish
let a = [1, 2, 3];
let doubled = a.iter().map(|x| x * 2).collect::<Vec<i32>>();
assert_eq!(vec![2, 4, 6], doubled);
_ 与turbfish一起使用:
let a = [1, 2, 3];
let doubled = a.iter().map(|x| x * 2).collect::<Vec<_>>();
assert_eq!(vec![2, 4, 6], doubled);

(五)迭代器转换
map()方法可以转换迭代器
创建一个迭代器,该迭代器每个元素是由原迭代器元素应用闭包得到。
可以这样考虑map(): 如果您有一个元素类型为A的迭代器,您想要元素类型为B的迭代器,则可以使用map(),传递一个把A转成B的闭包。
例子

let a = [1, 2, 3];
let mut iter = a.iter().map(|x| 2 * x);
assert_eq!(iter.next(), Some(2));
assert_eq!(iter.next(), Some(4));
assert_eq!(iter.next(), Some(6));
assert_eq!(iter.next(), None);

如果您正在做某种副作用,请首选for而不是map():
不要这样做:

(0..5).map(|x| println!("{x}"));// 它甚至不会执行,因为它很懒。Rust会就此警告您。

而是用:

for x in 0..5 {println!("{x}");
}

flat_map()
创建一个迭代器,其工作方式类似于map,但它会将嵌套的结构展平。
map非常有用,但仅当闭包产生值时才使用。 如果它产生一个迭代器,则存在一个额外的间接层。flat_map() 将自行删除这个间接层。
您可以把flat_map(f) 视为map(f).flatten()。
map的闭包为每个元素返回一个值,而flat_map ()的闭包为每个元素返回一个迭代器。
例子

let words = ["alpha", "beta", "gamma"];
// chars() 返回一个迭代器
let merged: String = words.iter().flat_map(|s| s.chars()).collect();
assert_eq!(merged, "alphabetagamma");

flatten()
创建一个去掉嵌套层的迭代器。比如二维向量变一维向量
例子

let data = vec![vec![1, 2, 3, 4], vec![5, 6]];
let flattened = data.into_iter().flatten().collec::<Vec<u8>>();
assert_eq!(flattened, &[1, 2, 3, 4, 5, 6]);let words = ["alpha", "beta", "gamma"];
// chars() 返回一个迭代器
let merged: String = words.iter().map(|s| s.chars()).flatten().collect();
assert_eq!(merged, "alphabetagamma");
您也可以用flat_map()来重写它
let words = ["alpha", "beta", "gamma"];
// chars() 返回一个迭代器
let merged: String = words.iter().flat_map(|s| s.chars()).collect();
assert_eq!(merged, "alphabetagamma");

展平一次只能删除一层嵌套:

let d3 = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]];
let d2 = d3.iter().flatten().collect::<Vec<_>>();
assert_eq!(d2, [&[1, 2], &[3, 4], &[5, 6], &[7, 8]]);
let d1 = d3.iter().flatten().flatten().collect::<Vec<_>>();
assert_eq!(d1, [&1, &2, &3, &4, &5, &6, &7, &8]);

在这里,我们看到flatten()仅删除了一层嵌套。三维数组变二维而不是一维。要获得一维,您必须再次flatten()。

(六)enumerate
创建一个迭代器,该迭代器元素是(i, val),其中i是当前迭代索引,val是迭代器返回的值。
enumerate()保持其计数为usize。
溢出行为
该方法无法防止溢出,因此枚举多个usize::MAX元素会产生错误的结果或panics。 如果启用了调试断言,则将保证panic。
Panics
如果要返回的索引将溢出usize,则返回的迭代器可能为panic。
例子

let a = ['a', 'b', 'c'];
let mut iter = a.iter().enumerate();
assert_eq!(iter.next(), Some((0, &'a')));
assert_eq!(iter.next(), Some((1, &'b')));
assert_eq!(iter.next(), Some((2, &'c')));
assert_eq!(iter.next(), None);

(七)逆转迭代器
rev
反转迭代器的方向。
通常,迭代器从左到右进行迭代。 使用rev() 之后,迭代器将改为从右向左进行迭代。
例子

let a = [1, 2, 3];
let mut iter = a.iter().rev();
assert_eq!(iter.next(), Some(&3));
assert_eq!(iter.next(), Some(&2));
assert_eq!(iter.next(), Some(&1));
assert_eq!(iter.next(), None);

(八)截取迭代器
take(n)
创建一个迭代器,它的元素是原迭代器的前n个元素。如果原迭代器元素数小于n,则返回原迭代器所有元素。
例子

let a = [1, 2, 3];
let mut iter = a.iter().take(2);
assert_eq!(iter.next(), Some(&1));
assert_eq!(iter.next(), Some(&2));
assert_eq!(iter.next(), None);
let v = [1, 2];
let mut iter = v.into_iter().take(5);
assert_eq!(iter.next(), Some(1));
assert_eq!(iter.next(), Some(2));
assert_eq!(iter.next(), None);

(九)其他
max
返回迭代器的最大元素。
如果几个元素最大相等,则返回最后一个元素。如果迭代器为空,则返回None。
请注意,由于NaN不可比较,f32/f64没有实现Ord。 您可以使用Iterator::reduce解决此问题:

assert_eq!([2.4, f32::NAN, 1.3].into_iter().reduce(f32::max).unwrap(),2.4);

例子

let a = [1, 2, 3];
let b: Vec = Vec::new();
assert_eq!(a.iter().max(), Some(&3));
assert_eq!(b.iter().max(), None);

min
返回迭代器的最小元素。
如果几个元素相等地最小,则返回第一个元素。 如果迭代器为空,则返回None。
请注意,由于NaN不可比较,f32/f64没有实现Ord。您可以使用Iterator::reduce解决此问题:

assert_eq!([2.4, f32::NAN, 1.3].into_iter().reduce(f32::min).unwrap(),1.3);

例子

let a = [1, 2, 3];
let b: Vec = Vec::new();
assert_eq!(a.iter().min(), Some(&1));
assert_eq!(b.iter().min(), None);

sum
对迭代器的元素求和。
获取每个元素,将它们添加在一起,然后返回结果。
空的迭代器将返回该类型的零值。
sum()可用于对任何实现Sum的类型求和,包括Option和Result。
Panics
当调用sum() 并返回原始整数类型时,如果计算溢出并且启用了调试断言,则此方法将为panic。
例子

let a = [1, 2, 3];
let sum: i32 = a.iter().sum();
assert_eq!(sum, 6);

相关文章:

rust迭代器

迭代器用来遍历容器。 迭代器就是把容器中的所有元素按照顺序一个接一个的传递给处理逻辑。 Rust中的迭代器 标准库中定义了Iterator特性 trait Iterator {type Item;fn next(&mut self) -> Option<Self::Item>; }实现了Iterator特性的结构体就是迭代器。 很多类…...

软件定制开发的优势与步骤|APP搭建|小程序

软件定制开发的优势与步骤|APP搭建|小程序 定制开发的优势&#xff1a; 1. 满足特定需求&#xff1a;定制开发可以根据客户的实际需求进行设计和开发&#xff0c;使得软件系统能够更好地满足客户的业务目标。 2. 优化用户体验&#xff1a;通过深入了解客户的需求&#xff0c;定…...

ERR_CONNECTION_REFUSED等非标准的HTTP错误状态码原因分析和解决办法

文章目录 一、DNS Resolution Failed1&#xff0c;DNS服务器故障2&#xff0c;DNS配置错误3&#xff0c;DNS劫持4&#xff0c;域名过期-5&#xff0c;其他网络问题 二、ERR_CONNECTION_REFUSED-"ERR_CONNECTION_REFUSED" 错误可能有多种原因 三、ERR_SSL_PROTOCOL_ER…...

瀑布流 - Vue3基于Grid布局简单实现一个瀑布流组件

瀑布流 - Vue3基于Grid布局简单实现一个瀑布流组件 前言 在学习Grid布局之时&#xff0c;我发现其是CSS中的一种强大的布局方案&#xff0c;它将网页划分成一个个网格&#xff0c;可以任意组合不同的网格&#xff0c;做出各种各样的布局&#xff0c;在刷某书和某宝首页时&…...

ES6面试题总结

1. 谈谈你对 ES6 的理解,为什么要学习es6? ES6是新一代的JS语言标准&#xff0c;对分JS语言核心内容做了升级优化&#xff0c;规范了JS使用标准&#xff0c;新增了JS原生方法&#xff0c;使得JS使用更加规范&#xff0c;更加优雅&#xff0c;更适合大型应用的开发。学习ES6是成…...

mybatisplus,jdbc 批量插入

1.测试用例 项目中遇到在做导入号码的时候我们会用到批量导入&#xff0c;提高入库的速度。接下来我们以10000条为测试用例。 1.1 批量执行sql语句 当需要成批插入或者更新记录时&#xff0c;可以采用Java的批量更新机制&#xff0c;这一机制允许多条语句一次性提交给数据库…...

如何使用IP归属地查询API来追踪网络活动

引言 在当今数字化世界中&#xff0c;了解网络活动的源头和位置对于网络安全、市场研究和用户体验至关重要。IP归属地查询API是一种强大的工具&#xff0c;可以帮助您追踪网络活动并获取有关IP地址的重要信息。本文将探讨如何使用IP归属地查询API来追踪网络活动&#xff0c;以…...

【SQL】S0 系列博文大纲

系列博文大纲 SQL 学习环境建议系列博文相关书籍系列博文大纲阶段进展 SQL 学习环境建议 对于 SQL 语言的学习&#xff0c;博主本地使用&#xff1a;MySQL DataGrip&#xff1b; MySQL 提供本地数据库服务&#xff1b; DataGrip IDE&#xff0c;承担编程运行测试任务&#xf…...

2023年8月体育用品行业数据分析(京东数据产品)

当前&#xff0c;亚运会临近&#xff0c;这也带动了国民对体育消费的热情&#xff0c;体育产品内销逐渐旺盛&#xff0c;“亚运经济”红利开始显现。鲸参谋数据显示&#xff0c;今年8月份&#xff0c;京东平台上体育用品行业的销量为185万&#xff0c;同比增长2%&#xff1b;销…...

国内高校镜像网站

国内各大高校开源镜像站 排名不分前后 清华大学&#xff1a;https://mirrors.tuna.tsinghua.edu.cn/ 北京大学&#xff1a;https://mirrors.pku.edu.cn/ 北京外国语大学&#xff1a;http://​ https://mirrors.bfsu.edu.cn/ ​ 北京理工大学&#xff1a;https://mirrors.bit.e…...

Linux安装kafka-manager

相关链接https://github.com/yahoo/kafka-manager/releases kafka-manager-2.0.0.2下载地址 百度云链接&#xff1a;https://pan.baidu.com/s/1XinGcwpXU9YBF46qkrKS_A 提取码&#xff1a;tzvg 一、安装部署 1.把kafka-manager-2.0.0.2.zip拷贝到目录 /opt/app/elk 2.解压…...

MYSQL索引——B+树讲解

B-/B树看 MySQL索引结构 B-树 B-树,这里的 B 表示 balance( 平衡的意思),B-树是一种多路自平衡的搜索树.它类似普通的平衡二叉树&#xff0c;不同的一点是B-树允许每个节点有更多的子节点。下图是 B-树的简化图. B-树有如下特点: 所有键值分布在整颗树中&#xff1b; 任何一…...

VB将十进制整数转换成16进制以内的任意进制数

VB将十进制整数转换成16进制以内的任意进制数 数值转换&#xff0c;能够将十进制整数转换成16进制以内的任意进制数 Private Function DecToN(ByVal x%, ByVal n%) As StringDim p() As String, y$, r%p Split("0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F", ",")I…...

基于SpringBoot+Vue的宠物领养饲养交流管理平台设计与实现

前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌&#x1f497; &#x1f447;&#x1f3fb;…...

【图像去噪】【TGV 正则器的快速计算方法】通过FFT的总(广义)变化进行图像去噪(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

windbg调试句柄问题

这里写自定义目录标题 winform&#xff0c;句柄资源不够强&#xff0c;程序crash句柄主程序c程序&#xff0c;加载的插件是c# dll&#xff0c;这时候如何用windbg调试dll库如果查看句柄和对象的关系!handle 怎么能知道哪个句柄是Form对话框的句柄如何查看句柄对应的类对象 winf…...

9月13-14日上课内容 第三章 ELK日志分析系统及部署实例

本章结构 ELK日志分析系统简介 ELK日志分析系统分为 Elasticsearch Logstash Kibana 日志处理步骤 1.将日志进行集中化管理 2.将日志格式化(Logstash) 并输出到Elasticsearch 3.对格式化后的数据进行索引和存储 (Elasticsearch) 4.前端数据的展示(Kibana) Elasticsearch介…...

服务器端应用的安装

前言&#xff1a;相信看到这篇文章的小伙伴都或多或少有一些编程基础&#xff0c;懂得一些linux的基本命令了吧&#xff0c;本篇文章将带领大家服务器如何部署一个使用django框架开发的一个网站进行云服务器端的部署。 文章使用到的的工具 Python&#xff1a;一种编程语言&…...

关于硬盘质量大数据分析的思考

近日&#xff0c;看到Backblaze分享了一遍关于硬盘运行监控数据架构的文章&#xff0c;觉得挺有意义的&#xff0c;本文就针对这方面跟大家聊聊。 作为一家在2021年在美国纳斯达克上市的云端备份公司&#xff0c;Backblaze一直保持着对外定期发布HDD和SSD的故障率稳定性质量报告…...

RK3568核心板分区空间不足,如何修改分区大小?

在对评估板进行开发验证时&#xff0c;时常会遇到根目录空间不足的情况&#xff0c;而在其他分区又有冗余空间&#xff0c;这时则需要对分区大小重新进行分配&#xff0c;合理化利用分区空间。 本文将基于HD-RK3568-IOT评估板主要讲解如何修改eMMC分区大小。 ​ 1. 分区表介绍…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度​

一、引言&#xff1a;多云环境的技术复杂性本质​​ 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时&#xff0c;​​基础设施的技术债呈现指数级积累​​。网络连接、身份认证、成本管理这三大核心挑战相互嵌套&#xff1a;跨云网络构建数据…...

synchronized 学习

学习源&#xff1a; https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖&#xff0c;也要考虑性能问题&#xff08;场景&#xff09; 2.常见面试问题&#xff1a; sync出…...

设计模式和设计原则回顾

设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)

🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

html-<abbr> 缩写或首字母缩略词

定义与作用 <abbr> 标签用于表示缩写或首字母缩略词&#xff0c;它可以帮助用户更好地理解缩写的含义&#xff0c;尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时&#xff0c;会显示一个提示框。 示例&#x…...

C++使用 new 来创建动态数组

问题&#xff1a; 不能使用变量定义数组大小 原因&#xff1a; 这是因为数组在内存中是连续存储的&#xff0c;编译器需要在编译阶段就确定数组的大小&#xff0c;以便正确地分配内存空间。如果允许使用变量来定义数组的大小&#xff0c;那么编译器就无法在编译时确定数组的大…...

短视频矩阵系统文案创作功能开发实践,定制化开发

在短视频行业迅猛发展的当下&#xff0c;企业和个人创作者为了扩大影响力、提升传播效果&#xff0c;纷纷采用短视频矩阵运营策略&#xff0c;同时管理多个平台、多个账号的内容发布。然而&#xff0c;频繁的文案创作需求让运营者疲于应对&#xff0c;如何高效产出高质量文案成…...

基于SpringBoot在线拍卖系统的设计和实现

摘 要 随着社会的发展&#xff0c;社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统&#xff0c;主要的模块包括管理员&#xff1b;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...

uniapp 集成腾讯云 IM 富媒体消息(地理位置/文件)

UniApp 集成腾讯云 IM 富媒体消息全攻略&#xff08;地理位置/文件&#xff09; 一、功能实现原理 腾讯云 IM 通过 消息扩展机制 支持富媒体类型&#xff0c;核心实现方式&#xff1a; 标准消息类型&#xff1a;直接使用 SDK 内置类型&#xff08;文件、图片等&#xff09;自…...

OCR MLLM Evaluation

为什么需要评测体系&#xff1f;——背景与矛盾 ​​ 能干的事&#xff1a;​​ 看清楚发票、身份证上的字&#xff08;准确率>90%&#xff09;&#xff0c;速度飞快&#xff08;眨眼间完成&#xff09;。​​干不了的事&#xff1a;​​ 碰到复杂表格&#xff08;合并单元…...