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搭建|小程序 定制开发的优势: 1. 满足特定需求:定制开发可以根据客户的实际需求进行设计和开发,使得软件系统能够更好地满足客户的业务目标。 2. 优化用户体验:通过深入了解客户的需求,定…...
ERR_CONNECTION_REFUSED等非标准的HTTP错误状态码原因分析和解决办法
文章目录 一、DNS Resolution Failed1,DNS服务器故障2,DNS配置错误3,DNS劫持4,域名过期-5,其他网络问题 二、ERR_CONNECTION_REFUSED-"ERR_CONNECTION_REFUSED" 错误可能有多种原因 三、ERR_SSL_PROTOCOL_ER…...
瀑布流 - Vue3基于Grid布局简单实现一个瀑布流组件
瀑布流 - Vue3基于Grid布局简单实现一个瀑布流组件 前言 在学习Grid布局之时,我发现其是CSS中的一种强大的布局方案,它将网页划分成一个个网格,可以任意组合不同的网格,做出各种各样的布局,在刷某书和某宝首页时&…...
ES6面试题总结
1. 谈谈你对 ES6 的理解,为什么要学习es6? ES6是新一代的JS语言标准,对分JS语言核心内容做了升级优化,规范了JS使用标准,新增了JS原生方法,使得JS使用更加规范,更加优雅,更适合大型应用的开发。学习ES6是成…...
mybatisplus,jdbc 批量插入
1.测试用例 项目中遇到在做导入号码的时候我们会用到批量导入,提高入库的速度。接下来我们以10000条为测试用例。 1.1 批量执行sql语句 当需要成批插入或者更新记录时,可以采用Java的批量更新机制,这一机制允许多条语句一次性提交给数据库…...
如何使用IP归属地查询API来追踪网络活动
引言 在当今数字化世界中,了解网络活动的源头和位置对于网络安全、市场研究和用户体验至关重要。IP归属地查询API是一种强大的工具,可以帮助您追踪网络活动并获取有关IP地址的重要信息。本文将探讨如何使用IP归属地查询API来追踪网络活动,以…...
【SQL】S0 系列博文大纲
系列博文大纲 SQL 学习环境建议系列博文相关书籍系列博文大纲阶段进展 SQL 学习环境建议 对于 SQL 语言的学习,博主本地使用:MySQL DataGrip; MySQL 提供本地数据库服务; DataGrip IDE,承担编程运行测试任务…...
2023年8月体育用品行业数据分析(京东数据产品)
当前,亚运会临近,这也带动了国民对体育消费的热情,体育产品内销逐渐旺盛,“亚运经济”红利开始显现。鲸参谋数据显示,今年8月份,京东平台上体育用品行业的销量为185万,同比增长2%;销…...
国内高校镜像网站
国内各大高校开源镜像站 排名不分前后 清华大学:https://mirrors.tuna.tsinghua.edu.cn/ 北京大学:https://mirrors.pku.edu.cn/ 北京外国语大学:http:// https://mirrors.bfsu.edu.cn/ 北京理工大学:https://mirrors.bit.e…...
Linux安装kafka-manager
相关链接https://github.com/yahoo/kafka-manager/releases kafka-manager-2.0.0.2下载地址 百度云链接:https://pan.baidu.com/s/1XinGcwpXU9YBF46qkrKS_A 提取码:tzvg 一、安装部署 1.把kafka-manager-2.0.0.2.zip拷贝到目录 /opt/app/elk 2.解压…...
MYSQL索引——B+树讲解
B-/B树看 MySQL索引结构 B-树 B-树,这里的 B 表示 balance( 平衡的意思),B-树是一种多路自平衡的搜索树.它类似普通的平衡二叉树,不同的一点是B-树允许每个节点有更多的子节点。下图是 B-树的简化图. B-树有如下特点: 所有键值分布在整颗树中; 任何一…...
VB将十进制整数转换成16进制以内的任意进制数
VB将十进制整数转换成16进制以内的任意进制数 数值转换,能够将十进制整数转换成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的宠物领养饲养交流管理平台设计与实现
前言 💗博主介绍:✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战✌💗 👇🏻…...
【图像去噪】【TGV 正则器的快速计算方法】通过FFT的总(广义)变化进行图像去噪(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
windbg调试句柄问题
这里写自定义目录标题 winform,句柄资源不够强,程序crash句柄主程序c程序,加载的插件是c# dll,这时候如何用windbg调试dll库如果查看句柄和对象的关系!handle 怎么能知道哪个句柄是Form对话框的句柄如何查看句柄对应的类对象 winf…...
9月13-14日上课内容 第三章 ELK日志分析系统及部署实例
本章结构 ELK日志分析系统简介 ELK日志分析系统分为 Elasticsearch Logstash Kibana 日志处理步骤 1.将日志进行集中化管理 2.将日志格式化(Logstash) 并输出到Elasticsearch 3.对格式化后的数据进行索引和存储 (Elasticsearch) 4.前端数据的展示(Kibana) Elasticsearch介…...
服务器端应用的安装
前言:相信看到这篇文章的小伙伴都或多或少有一些编程基础,懂得一些linux的基本命令了吧,本篇文章将带领大家服务器如何部署一个使用django框架开发的一个网站进行云服务器端的部署。 文章使用到的的工具 Python:一种编程语言&…...
关于硬盘质量大数据分析的思考
近日,看到Backblaze分享了一遍关于硬盘运行监控数据架构的文章,觉得挺有意义的,本文就针对这方面跟大家聊聊。 作为一家在2021年在美国纳斯达克上市的云端备份公司,Backblaze一直保持着对外定期发布HDD和SSD的故障率稳定性质量报告…...
RK3568核心板分区空间不足,如何修改分区大小?
在对评估板进行开发验证时,时常会遇到根目录空间不足的情况,而在其他分区又有冗余空间,这时则需要对分区大小重新进行分配,合理化利用分区空间。 本文将基于HD-RK3568-IOT评估板主要讲解如何修改eMMC分区大小。 1. 分区表介绍…...
Linux系统怎么修改主机名
【微|信|公|众|号:厦门微思网络】 1.备份主机名文件 首先redhat修改主机名,在进行任何修改之前,请务必备份主机名文件。这样,即使出现意外情况,你也能够轻松恢复到原始状态。使用以下命令备份主机名文件࿱…...
BroadcastChannel方法跨浏览器窗口通信
1. 描述 同源 的不同浏览器窗口,Tab 页,frame 或者 iframe 下的不同文档之间可以通过 BroadcastChannel 相互通信。 2. 构造函数 通过 BroadcastChannel 类传入的参数创建实例,传入的参数将指定通道名称,在同源环境下该通道可以…...
山石网科国产化防火墙,打造全方位边界安全解决方案
互联网的快速发展促进了各行各业的信息化建设,但也随之带来了诸多网络安全风险。大部分组织机构采用统一互联网接入方案,互联网出口承担着内部用户访问互联网的统一出口和对外信息服务的入口,因此在该区域部署相匹配的安全防护手段必不可少。…...
AVL 树
文章目录 一、AVL 树的概念二、AVL 树的实现1. AVL 树的存储结构2. AVL 树的插入 一、AVL 树的概念 在 二叉搜索树 中,当我们连续插入有序的数据时,二叉搜索树可能会呈现单枝树的情况,此时二叉搜索树的查找效率为 O(N) 俄罗斯的两位数学家 …...
ggplot2做图(填坑中)
数据 df <- data.frame(x 1:10, y 1:10, f c(rep("A", 5), rep("B", 5))) 做图 1. 散点图 (scatter plot) # scatter plot scatter_plot <- function(df, metadata) {identical(rownames(df), rownames(metadata))data <- cbind(df, metada…...
Python日志处理器,同时打印到控制台和保存到文件中,并保证格式一致
使用logging模块的时候,默认是输出到控制台的,当然也可以配置输出到文件中,但是当你配置了文件后,控制台的输出就消失了,所以,需要一个策略即能保存到文件中,又能输出到控制台中。 下面是我做的…...
JavaWeb后端开发登录操作 登录功能 通用模板/SpringBoot整合
登录功能的思路 前端会传入两个参数:用户名和密码 在用户表中查询用户名,并校对相应的密码(涉及查询操作) SQL语句 select * from emp where username jingyong and password 123456; 如果有则成功,没有则登录失败.不可能为多个,因为添加了unique唯一约束,最终只会有一条 …...
The 2023 ICPC Asia Regionals Online Contest (1)(A D I J K L)
The 2023 ICPC Asia Regionals Online Contest (1)(A D I J K L) PTA | 程序设计类实验辅助教学平台 A Qualifiers Ranking Rules(模拟) 考虑先对第一场和第二场分别去重(取最好) , 归并排序后再次去重即可。 #include<bits/stdc.h> using namespace std;…...
C++ PrimerPlus 复习 第七章 函数——C++的编程模块(上)
第一章 命令编译链接文件 make文件 第二章 进入c 第三章 处理数据 第四章 复合类型 (上) 第四章 复合类型 (下) 第五章 循环和关系表达式 第六章 分支语句和逻辑运算符 第七章 函数——C的编程模块(上ÿ…...
2.求循环小数
题目 对于任意的真分数 N/M ( 0 < N < M ),均可以求出对应的小数。如果采用链表表示各个小数,对于循环节采用循环链表表示,则所有分数均可以表示为如下链表形式。 输入: N M 输出: 转换…...
网站开发 . 漫游指南/企业培训课程名称大全
目录 贝叶斯定理 贝叶斯分类 朴素贝叶斯分类器 贝叶斯网络 VS 朴素贝叶斯 贝叶斯网络 条件概率表集合 贝叶斯网络的构造…...
网站建设优势/腾讯朋友圈广告怎么投放
docker run --namemydemo -p -d 2222:80 imagename --name: 指定容器名称 -p:指定容器端口号 -d:指定容器后台运行转载于:https://www.cnblogs.com/lishidefengchen/p/10709828.html...
万网域名注册网站/怎么自己弄一个网站
1、$(document).ready(function(){})dom加载完成后触发window.onload只能注册一个方法页面所有内容加载完成后触发(图片,css,js都加缩写$(function(){})2、jQuery对象(包装集) dom对象var div document.getElementById("id") dom对…...
建立 网站服务器/网络营销案例分析题
相关专业领域 01. 程序设计 (算法编程 有趣的程序编程 病毒/木马编程等)02. 逆向分析 (软件破解 病毒/木马分析 还原源代码等)03. 漏洞挖掘以及利用 (利用综合能力挖掘/分析/利用漏洞等)04. 社会工程学 (通过社交行为获取敏感信息等)05. 模糊测试 (模糊测试软件漏洞等)06. 渗透…...
成都网站建设 今网科技/网站推广的四个阶段
TimeUnits 可以为 Seconds, Minutes, Hours 或 Days (或仅使用这些单词的首个字母). 如果 Value 为空, 则使用当前时间代替. 同样地, 如果 Var 是空变量, 则使用当前时间代替. 计算隔几天前(后)是哪个日期 var1 ; 赋值为空, 这样下面将会使用当前时…...
wordpress三级联动/免费网站推广网站不用下载
控制论的创始人维纳认为:信息就是信息,不是物质也不是能量。也就是说,信息与物质、能量是有区别的。同时,信息与物质、能量之间也存在着密切的关系。物质、能量、信息是构成现实世界的三大要素。只要事物之间的相互联系和相互作用…...