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

家具设计作品集网站建设优化价格

家具设计作品集,网站建设优化价格,怎么做公司免费网站,网页游戏百度Rust入门之迭代器(Iterators) 本文已同步本人博客网站 本文相关源码已上传Github 前言 迭代器(Iterators)是 Rust 中最核心的工具之一,它不仅是遍历集合的抽象,更是 Rust 零成本抽象(Zero-Co…

Rust入门之迭代器(Iterators)

本文已同步本人博客网站
本文相关源码已上传Github

前言

迭代器(Iterators)是 Rust 中最核心的工具之一,它不仅是遍历集合的抽象,更是 Rust 零成本抽象(Zero-Cost Abstractions)和所有权系统完美结合的典范。与其他语言不同,Rust 的迭代器在提供高效遍历能力的同时,通过编译器的严格检查,确保内存安全和性能优化,从而避免了其他语言中常见的迭代器失效或越界访问等问题。本文将跟随《Rust 程序设计语言》通过剖析迭代器的设计原理、使用方法及底层机制,帮助你掌握这一工具,并写出更符合 Rust 哲学的代码。

定义

迭代器模式允许你依次对一个序列中的项执行某些操作。迭代器iterator)负责遍历序列中的每一项并确定序列何时结束的逻辑。

在 Rust 中,迭代器是 惰性的lazy),这意味着在调用消费迭代器的方法之前不会执行任何操作。

fn main() {let v1 = vec![1, 2, 3];// 创建了一个迭代器,这段代码本身并没有执行任何有用的操作。let v1_iter = v1.iter();
}
  • 惰性求值的优势:避免不必要的计算开销,例如处理无限序列或仅在需要时生成元素。
  • 实际应用场景:处理大型数据集时,惰性迭代器可以节省内存,只在需要时加载数据。
  • 显式消费的必要性:必须调用消费方法(如collect())才能触发实际迭代,否则不会执行任何操作。

使用for 关键字打印出数组中的元素。

fn main() {let v1 = vec![1, 2, 3];// 创建了一个迭代器,这段代码本身并没有执行任何有用的操作。let v1_iter = v1.iter();for val in v1_iter {println!("Got: {}", val);}
}

Iterator Trait 和 next方法

迭代器都实现了一个叫做 Iterator 的定义于标准库的 trait,源码如下:

pub trait Iterator {type Item;fn next(&mut self) -> Option<Self::Item>;// 此处省略了方法的默认实现
}

type ItemSelf::Item,它们定义了 trait 的 关联类型。意味着实现 Iterator trait的时候必须定义一个Item,用于next 函数的返回元素的类型。

next函数

nextIterator 实现者被要求定义的唯一方法:next 方法,该方法每次返回迭代器中的一个项,封装在 Some 中,并且当迭代完成时,返回 None

如果调用next函数,迭代器变量要声明为可变的。在迭代器上调用 next 方法会改变迭代器内部的状态,每次调用next函数都会消费迭代器。

#[cfg(test)]
mod tests {#[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);}
}

代码中调用了四次next函数,如果有值返回的是由Some包着的引用,如果没有值了返回None。

根据需要可以获取不同引用所有权的迭代器:

  1. iter() 创建的是不可变引用的迭代器。
  2. into_iter() 能获得数组的的所有权,并返回具有所有权的值。
  3. iter_mut() 创建的是一个可以遍历到可变引用的迭代器。
方法元素类型所有权原集合后续可用性
iter()&T借用
iter_mut()&mut T可变借用
into_iter()T转移所有权

示例:所有权发生转移,println!不能再使用v1

let v1 = vec![1, 2, 3];
let v1_iter = v1.into_iter();
// println!("{:?}", v1); // 编译错误:value borrowed after move

消费迭代器的方法

Iterator trait 有一系列不同的由标准库提供默认实现的方法。我们可以在 Iterator trait 的标准库 API 文档中找到所有这些方法。一些方法在其定义中调用了 next 方法,这也就是为什么在实现 Iterator trait 时要求实现 next 方法的原因。这些调用 next 方法的方法被称为 消费适配器consuming adaptors),因为调用它们会消耗迭代器。一个消费适配器的例子是 sum 方法。这个方法获取迭代器的所有权并反复调用 next 来遍历迭代器,因而会消费迭代器。在遍历过程中,它将每个项累加到一个总和中,并在迭代完成时返回这个总和。

点开sum函数源码,并没看到调用next方法,这里其实是使用了 Sum traitIterator::sum() 的实现通过将遍历和累加委托给 Sum trait,只要能确认迭代器中存放的什么类型就能由对应的trait实现求和。后续这里我专门写一篇文章探究学习一下。

    #[stable(feature = "iter_arith", since = "1.11.0")]fn sum<S>(self) -> SwhereSelf: Sized,S: Sum<Self::Item>,{Sum::sum(self)}
  • 标准库sum方法文档:https://doc.rust-lang.org/stable/std/iter/trait.Iterator.html#method.sum

使用sum() 对集合当中的元素求和

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

创建迭代器的方法

Iterator trait 中定义了另一类方法,被称为 迭代适配器iterator adaptors),它们不会消耗当前的迭代器,而是通过改变原始迭代器的某些方面来生成不同的迭代器,如 map方法。

    #[test]fn test_map() {let v1 = vec![1,2,3];let v3: Vec<_> = v1.iter().map(|i| i + 1).collect();assert_eq!(v3, vec![2, 3, 4]);}

由于 map 接受一个闭包,因此我们可以指定希望在每个元素上执行的任何操作。这是一个很好的例子,展示了如何通过闭包来自定义某些行为,同时复用 Iterator trait 提供的迭代行为。

可以链式调用多个迭代器适配器来以一种可读的方式进行复杂的操作。不过因为所有的迭代器都是惰性的,你必须调用一个消费适配器方法,才能从这些迭代器适配器的调用中获取结果。

消费迭代器的方法叫做消费适配器

创建迭代器的方法 叫做迭代适配器

使用捕获其环境的闭包

很多迭代器适配器接受闭包作为参数,而我们通常会指定捕获其环境的闭包作为迭代器适配器的参数。

在这里再介绍一个迭代适配器filter(),也利用了闭包中的一个特性:通过闭包捕获定义它的环境中的值(跳转闭包相关文章)。

我们使用 filter 方法来获取一个闭包。该闭包从迭代器中获取一项并返回一个 bool。如果闭包返回 true,其值将会包含在 filter 提供的新迭代器中。如果闭包返回 false,其值不会被包含。

使用 filter 方法和一个捕获 shoe_size 的闭包,示例代码如下:

#[derive(PartialEq, Debug)]
struct Shoe {size:i32,style: String,
}fn shoes_in_size(shoes: Vec<Shoe>, shoe_size: i32) -> Vec<Shoe> {// 必须使用into_iter() 获得数组所有权,因为collect 要求生成一个Vec<Shoe>shoes.into_iter().filter(|s| s.size == shoe_size).collect()
}
#[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")},]);}

shoes_in_size 函数获取一个鞋子 vector 的所有权和一个鞋码作为参数。它返回一个只包含指定鞋码的鞋子的 vector。

shoes_in_size 函数体中调用了 into_iter 来创建一个获取 vector 所有权的迭代器。接着调用 filter 将这个迭代器适配成一个只含有那些闭包返回 true 的元素的新迭代器。

闭包从环境中捕获了 shoe_size 变量并使用其值与每一只鞋的大小作比较,只保留指定鞋码的鞋子。最终,调用 collect 将迭代器适配器返回的值收集进一个 vector 并返回。

这个测试展示当调用 shoes_in_size 时,返回的只会是与我们指定的鞋码相同的鞋子。


在代码中使用的是into_iter(),没有使用iter()是为什么呢? 这里再分析一下他们的区别:

iter()into_iter() 的核心区别

  • iter():生成一个 不可变引用 的迭代器,元素类型为 &T。原集合保留所有权,后续仍可使用。
  • into_iter():生成一个 拥有所有权 的迭代器,元素类型为 T。原集合被消耗(所有权转移),后续无法再使用。

调用collect()方法 试图将引用类型 &Shoe 收集到 Vec<Shoe> 中,但 Vec<Shoe> 只能存储 Shoe 类型的元素,不能存储引用,所以需要获得所有权。使用 into_iter() 是为了将元素的所有权从原集合转移到新集合中,确保 collect() 可以直接生成 Vec<Shoe>,避免类型不匹配和克隆开销。这是 Rust 所有权系统和类型安全性的直接体现。

http://www.dtcms.com/wzjs/560923.html

相关文章:

  • 网站被做跳转怎么办网站分为的风格
  • html5网站建站书网站建设后台怎么弄
  • 厦门百度网站建设企业vi设计案例欣赏
  • 建设网站怎么加购物车大朗做网站的
  • 企业网站制作建站公司江西城乡建设部网站首页
  • php无版权企业网站管理系统自动生成app
  • 公司营销型网站建设查找北京国互网网站建设
  • 莱芜市网站建设设计刷外链工具
  • 怎么做非法彩票网站wordpress下载页插件下载
  • 网站策划书ppt1688精品货源网站入口
  • 网站可以分为哪些类型中国十大品牌设计公司
  • 珠宝设计制作培训梅州网站优化
  • 网站建设就找奇思网络免费企业网站管理系统
  • 响应式网站用什么做WordPress自动采集豆瓣评分
  • 深圳哪里有做网站网站需求分析报告
  • 江苏网站开发盘锦做网站建设的
  • wordpress 建站容易吗建设网站是否应当摊销
  • 东营市建设项目工伤保险是哪个网站东圃做网站的公司
  • 做教育网站有什么好处论坛程序做导航网站
  • 东营长安网站建设如何给网站加二级域名
  • 头条网站开发云南俊发建设集团网站
  • 软件开发建设网站宁波seo推广咨询
  • 仿腾讯游戏网站源码wordpress文章页样式修改
  • 个人备案能做公司网站吗常用个人网站是什么
  • 展示型网站包含哪些模块成都犀牛网站建设
  • 免费公司建站网站设计怎么自学
  • 营销型网站应必备的七大功能网站的字体做多大合适
  • 根据网站做软件h5类型的网站是怎么做的
  • 教育行业网站模板网站建设需要费用
  • 什么网站做推广seo 论坛