【Rust中的迭代器】

Rust中的迭代器

  • 什么是迭代
  • 什么是迭代器
    • C++中的迭代器
  • Rust中的迭代器
      • rust中的 iter,iter_mut, into_iter
      • rust中的“指针移动”
      • rust中的IntoIterator 特征实现
      • collect
      • enumerate可以拿到索引
  • 总结


什么是迭代

迭代是指,在一个过程中反复重复,不断推进。在计算机领域,迭代是重复执行某一个过程的方法,每一次执行都基于上一次执行的结果。


什么是迭代器

Iterators are used to access and iterate through elements of data structures (vectors, sets, etc.), by “pointing” to them.
迭代器用于接入和迭代数据结构中的元素,通过"指向"他们,在几乎所有编程语言中,迭代器的功效均是如此。

C++中的迭代器

代码示例:

// 创建一个存储字符串的vector
vector<string> cars = {"Volvo", "BMW", "Ford", "Mazda"};// 声明一个字符串vector的迭代器(以下均称作iterator)
vector<string>::iterator it;//通过iterator循环获取数组中的字符串数据.
for (it = cars.begin(); it != cars.end(); ++it) {cout << *it << "\n";
}

上述代码中,第二行便是声明了一个迭代器,在循环中,通过begin()方法将vector中的第一个迭代器与之赋值,取到了指向数组中第一个元素的pointer,再通过for不断向后迭代,直至达到end(),即数组中最后一个元素的后一个位置,需要注意的是,begin()和end(),在代码中也可以看得出,他们并不是属于迭代器方法,而属于数据结构。

Rust中的迭代器

实现了Iterator特征的是迭代器,如果开发者需要特定的迭代方法,需要自己实现Iterator特征
代码示例:

fn main() {let vec = vec![1, 2, 3];let veciter = vec.iter();   //<--迭代器初始化for val in veciter {println!("{}", val);}
}

rust中迭代器的初始化均是由是由迭代器的数据结构初始化赋值.如上述代码中的vec.iter();,具体的,我们可以进入到源码看看iter做了什么。

#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T, A: Allocator> IntoIterator for &'a Vec<T, A> {type Item = &'a T;type IntoIter = slice::Iter<'a, T>;fn into_iter(self) -> Self::IntoIter {self.iter()}
}

再进一步观察self.iter()源码:

    #[stable(feature = "rust1", since = "1.0.0")]#[inline]pub fn iter(&self) -> Iter<'_, T> {Iter::new(self)}

iter通过调用Iter::new(self),从而初始化了一个数组迭代器.进一步看Iter::new(Self):

impl<'a, T> Iter<'a, T> {#[inline]pub(super) fn new(slice: &'a [T]) -> Self {let len = slice.len();let ptr: NonNull<T> = NonNull::from(slice).cast();// SAFETY: Similar to `IterMut::new`.unsafe {let end_or_len =if T::IS_ZST { without_provenance(len) } else { ptr.as_ptr().add(len) };Self { ptr, end_or_len, _marker: PhantomData }}}

可以看到的是,new中也是获取了切片长度和指针,这样在迭代过程中,指针安全高效的执行每一次迭代并找到数据.

rust中的 iter,iter_mut, into_iter

iter:引用,iter_mut:可变引用,into_iter:夺取所有权(如果你只想遍历一次后不再使用)

rust中的“指针移动”

C++中的迭代器,通过pointer向后移动来迭代数据,rust则通过next:

            #[inline]fn next(&mut self) -> Option<$elem> {// could be implemented with slices, but this avoids bounds checks// SAFETY: The call to `next_unchecked` is// safe since we check if the iterator is empty first.unsafe {if is_empty!(self) {None} else {Some(self.next_unchecked())}}}

每一次的向后迭代数据,都会执行一次next,而next的执行总是安全的,它先会检查数据是否为空,不为空则返回下一个Option元素。

rust中的IntoIterator 特征实现

在上述源码Vec.iter()不难发现,rust为vec实现了IntoIterator 特征,分别对应于三种所有权模式,而IntoIterator 特征也不难理解,即将vec转换到迭代器,成为迭代器便可以迭代数组中的数据。

collect

Transforms an iterator into a collection.
collect() can take anything iterable, and turn it into a relevant collection. This is one of the more powerful methods in the standard library, used in a variety of contexts.
The most basic pattern in which collect() is used is to turn one collection into another. You take a collection, call iter on it, do a bunch of transformations, and then collect() at the end.
collect() can also create instances of types that are not typical collections. For example, a String can be built from chars, and an iterator of Result<T, E> items can be collected into Result<Collection, E>. See the examples below for more.
Because collect() is so general, it can cause problems with type inference. As such, collect() is one of the few times you’ll see the syntax affectionately known as the ‘turbofish’: ::<>. This helps the inference algorithm understand specifically which collection you’re trying to collect into.

简单来说,collect()可以接受任何可迭代的东西,并将其转换为相关的集合。使用collect()的最基本模式是将一个集合转换为另一个集合。你取一个集合,调用iter,做一堆转换,然后在最后取collect()。

代码示例:

use std::collections::VecDeque;
fn main() {let a = [1, 2, 3];let doubled: VecDeque<i32> = a.iter().map(|&x| x * 2).collect();assert_eq!(2, doubled[0]);assert_eq!(4, doubled[1]);assert_eq!(6, doubled[2]);
}

上述代码既将vec转换成VecDeque。

enumerate可以拿到索引

如果开发者想要使用到数据结构中的索引,使用enumerate可以做到
代码示例:

fn main() {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);
}

总结

迭代器可定制化,通常用于数据结构的迭代遍历,有很多方便的方法使用用以实现不同的目的,可以参考rust std.

“我们都无法确定选择是否正确,只是努力把选择变得正确.”

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

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

相关文章

Unity3D学习FPS游戏(9)武器音效添加、创建敌人模型和血条

前言&#xff1a;虽然已经实现了基本玩家操作&#xff0c;但是游戏运行起来并没有音效。既然是FPS游戏有了玩家和武器&#xff0c;肯定还得有敌人。本篇演示如何给武器添加音效和创建敌人。 武器音效添加和创建敌人 武器音效添加Audio Source代码控制 创建敌人目标敌人模型敌人…

【算法】Floyd多源最短路径算法

目录 一、概念 二、思路 三、代码 一、概念 在前面的学习中&#xff0c;我们已经接触了Dijkstra、Bellman-Ford等单源最短路径算法。但首先我们要知道何为单源最短路径&#xff0c;何为多源最短路径 单源最短路径&#xff1a;从图中选取一点&#xff0c;求这个点到图中其他…

Docker安装MongoDB详解(mongo.latest)

一、MongoDB介绍 MongoDB是一种基于分布式文件存储的数据库&#xff0c;使用C语言开发&#xff0c;旨在为Web应用提供可扩展且高性能的数据存储解决方案。作为一种介于关系数据库和非关系数据库之间的技术&#xff0c;MongoDB具有强大的功能和高效的性能&#xff0c;特别适用于…

金箍棒变化-第15届蓝桥杯国赛Scratch初/中级组真题第1题

[导读]&#xff1a;超平老师的《Scratch蓝桥杯真题解析100讲》已经全部完成&#xff0c;后续会不定期解读蓝桥杯真题&#xff0c;这是Scratch蓝桥杯真题解析第193讲。 如果想持续关注Scratch蓝桥真题解读&#xff0c;可以点击《Scratch蓝桥杯历年真题》并订阅合集&#xff0c;…

简单的 docker 部署ELK

简单的 docker 部署ELK 这是我的运维同事部署ELK的文档&#xff0c;我这里记录转载一下 服务规划 架构: Filebeat->kafka->logstash->ES kafka集群部署参照: kafka集群部署 部署服务程序路径/数据目录端口配置文件elasticsearch/data/elasticsearch9200/data/elas…

Unity XR Interaction Toolkit 开发教程(3)快速配置交互:移动、抓取、UI交互【3.0以上版本】

获取完整课程以及答疑&#xff0c;工程文件下载&#xff1a; https://www.spatialxr.tech/ 视频试看链接&#xff1a; 3.快速配置交互&#xff1a;移动、抓取、UI交互【Unity XR Interaction Toolkit 跨平台开发教程】&#xff08;3.0以上版本&#xff09; 系列教程专栏&…

深度体验SCNet超算平台:SCNet「AI跃升季」·谁是下一个“AI”跃人?

平时做大模型训练的时候总是苦于没有服务器资源来做微调实验&#xff0c;于是这次深度体验了一下SCNet超算平台。 SCNet超算平台是一个超算互联网计算服务平台&#xff0c;有着更大更全更专业的超级算力。显卡从异构加速卡到A800都有。 本次我尝试了大模型的推理和微调。 第一…

求助帖【如何学习核磁共振的原理】

最近提前进组了 我完全不懂磁共振的相关知识 想问问各位大佬有没有推荐的学习路线 或者是学习资料、论坛都可以的&#xff08;我做的方向是磁共振成像技术&#xff09; 老师给了一本书&#xff0c;但是有点看不懂&#xff0c;全英文的 叫Principles Of Magnetic Resonance …

MySQL查询where中包含多个in条件问题

示例&#xff1a; select * from x_table where a in (1,2,3) and b in (4,8) 上面这种查询方法&#xff0c;如果可以通过a和b唯一确定一条数据&#xff0c;但a和b列可以有相同值时&#xff0c;会造成查询数据不准确。 验证&#xff1a; 假设有以下数据&#xff08;手机号为…

HiveSQL 中判断字段是否包含某个值的方法

HiveSQL 中判断字段是否包含某个值的方法 在 HiveSQL 中&#xff0c;有时我们需要判断一个字段是否包含某个特定的值。下面将介绍几种常用的方法来实现这个功能。 一、创建示例表并插入数据 首先&#xff0c;我们创建一个名为employee的表&#xff0c;并插入一些示例数据&am…

python-读写Excel:openpyxl-(4)下拉选项设置

使用openpyxl库的DataValidation对象方法可添加下拉选择列表。 DataValidation参数说明&#xff1a; type&#xff1a; 数据类型("whole", "decimal", "list", "date", "time", "textLength", "custom"…

求平面连接线段组成的所有最小闭合区间

这个功能确实非常实用&#xff0c;我在过去开发地面分区编辑器时就曾应用过这一算法。最近&#xff0c;在新产品的开发中再次遇到了类似的需求。尽管之前已经实现过&#xff0c;但由于长时间未接触&#xff0c;对算法的具体细节有所遗忘&#xff0c;导致重新编写时耗费了不少时…

springboot - 定时任务

定时任务是企业级应用中的常见操作 定时任务是企业级开发中必不可少的组成部分&#xff0c;诸如长周期业务数据的计算&#xff0c;例如年度报表&#xff0c;诸如系统脏数据的处理&#xff0c;再比如系统性能监控报告&#xff0c;还有抢购类活动的商品上架&#xff0c;这些都离不…

ES管理工具Cerebro 0.8.5 Windows版本安装及启动

前言&#xff1a; Cerebro 的下载地址 https://github.com/lmenezes/cerebro/releases Cerebro 默认监听IP 0.0.0.0 &#xff0c;默认端口9000&#xff0c;访问地址&#xff1a;http://localhost:9000 启动 cmd命令到安装目录下&#xff1a;cerebro-0.8.5\bin 执行命令 ce…

Flutter 正在切换成 Monorepo 和支持 workspaces

其实关于 Monorepo 和 workspaces 相关内容在之前《Dart 3.5 发布&#xff0c;全新 Dart Roadmap Update》 和 《Flutter 之 ftcon24usa 大会&#xff0c;创始人分享 Flutter 十年发展史》 就有简单提到过&#xff0c;而目前来说刚好看到 flaux 这个新进展&#xff0c;所以就再…

[论文][环境]3DGS+Colmap环境搭建_WSL2_Ubuntu22.04 - 副本

0. 前言 仅使用Ubuntu进行场景编译&#xff0c;场景渲染查看则使用Windows下官方提供的编译好的预编译包打开即可&#xff0c;非常方便&#xff08;要注意即使是预编译版本&#xff0c;Windows端也应该安装VS和CUDA Toolkit&#xff0c;要注意的是&#xff0c;最新的SIBR预编译…

json-server的使用(根据json数据一键生成接口)

一.使用目的 在前端开发初期&#xff0c;后端 API 可能还未完成&#xff0c;json-server 可以快速创建模拟的 RESTful API&#xff0c;帮助前端开发者进行开发和测试。 二.安装 npm install json-server //局部安装npm i json-server -g //全局安装 三.使用教程 1.准备一…

导入和部署自定义 LLM 大模型

本文以【Qwen2-7B-Instruct】模型为例&#xff0c;指导如何将自定义大模型导入到 TI 平台&#xff0c;并使用平台内置推理镜像部署大模型对话推理服务。 前置要求 申请 CFS 本文所涉及到的操作需要通过 CFS 存储模型文件&#xff0c;详情请查看创建文件系统及挂载点。 操作…

开源办公软件 ONLYOFFICE 深入探索

文章目录 引言1. ONLYOFFICE 创建的背景1. 1 ONLYOFFICE 项目启动1. 2 ONLYOFFICE 的发展历程 2. 核心功能介绍2. 1 桌面编辑器2. 1. 1 文档2. 1. 2 表格2. 1. 3 幻灯片 2. 2 协作空间2. 3 文档编辑器 - 本地部署版 3. 技术介绍4. 安装5. 优势与挑战6. 个人体验7. 强大但不止于…

HTTP慢速攻击原理及解决办法

目录 引言 HTTP慢速攻击原理 解决办法 Nginx Tomcat 华宇TAS IIS 结论 引言 HTTP慢速攻击&#xff08;Slow HTTP Attack&#xff09;是一种拒绝服务攻击&#xff08;DoS&#xff09;&#xff0c;攻击者通过故意缓慢地发送HTTP请求来耗尽服务器资源&#xff0c;导致合法…