rust学习-迭代器

这篇具有很好参考价值的文章主要介绍了rust学习-迭代器。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

迭代器的实现方式提供了对多种不同的序列使用相同逻辑的灵活性
没有迭代器时只能用索引,迭代器处理了所有这些逻辑,减少了重复代码,消除了潜在的混乱

示例

fn main() {
    let v1 = vec![1, 2, 3];
    let v1_iter = v1.iter();

    // 无需使 v1_iter 可变,因为 for 循环会获取 v1_iter 的所有权并在后台使 v1_iter 可变
    for val in v1_iter {
        println!("Got: {}", val);
    }
}

原理

迭代器都实现了一个叫做 Iterator 的定义于标准库的 trait

pub trait Iterator {
    // type Item 和 Self::Item 定义了 trait 的 关联类型,associated type
    // 实现 Iterator trait 要求同时定义一个 Item 类型
    // 这个 Item 类型被用作 next 方法的返回值类型
    type Item;

    // next 一次返回迭代器中的一个项,封装在 Some 中
    // 当迭代器结束时,它返回 None
    fn next(&mut self) -> Option<Self::Item>;

    // 此处省略了方法的默认实现
}

使用iter执行一个个的遍历

#[test]
fn iterator_demonstration() {
    let v1 = vec![1, 2, 3];
    // v1_iter 可变
    // 在迭代器上调用 next 方法改变了迭代器中用来记录序列位置的状态
    // 从 next 调用中得到的值是 vector 的不可变引用
    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);
}

iter:生成一个不可变引用的迭代器
into_iter:获取 v1 所有权并返回拥有所有权的迭代器
iter_mut:迭代可变引用

消费适配器

调用它们会消耗迭代器
比如sum:获取迭代器的所有权并反复调用 next 来遍历迭代器,因而会消费迭代器。当其遍历每一个项时,它将每一个项加总到一个总和并在迭代完成时返回总和

#[test]
fn iterator_sum() {
    let v1 = vec![1, 2, 3];
    let v1_iter = v1.iter();
    
    // 调用 sum 之后不再允许使用 v1_iter 因为调用 sum 时它会获取迭代器的所有权
    let total: i32 = v1_iter.sum();
    assert_eq!(total, 6);
}

迭代器适配器

将当前迭代器变为不同类型的迭代器。
可以链式调用多个迭代器适配器。
因为所有迭代器都惰性,必须调用一个消费适配器方法以便获取迭代器适配器调用的结果

使用闭包自定义行为同时,复用 Iterator trait 提供的迭代行为

let v1: Vec<i32> = vec![1, 2, 3];
// 调用 map 方法创建一个新迭代器,调用 collect 方法消费新迭代器并创建一个 vector
let v2: Vec<_> = v1.iter().map(|x| x + 1).collect();
assert_eq!(v2, vec![2, 3, 4]);

// 编译如下代码将会warn,因为惰性迭代器没人使用,需要像上述那样,用collect触发下使用
// v1.iter().map(|x| x + 1);

使用闭包获取环境

使用 filter 迭代器适配器和捕获环境的闭包

迭代器的 filter 方法获取一个使用迭代器的每一个项并返回布尔值的闭包。如果闭包返回 true,其值将会包含在 filter 提供的新迭代器中。
如果闭包返回 false,其值不会包含在结果迭代器中

#[derive(PartialEq, Debug)]
struct Shoe {
    size: u32,
    style: String,
}

fn shoes_in_my_size(shoes: Vec<Shoe>, shoe_size: u32) -> Vec<Shoe> {
    // into_iter:获取一个vector 的所有权
    shoes.into_iter()
        // shoe_size 是环境,函数做不到,但是闭包可以做到
        // filter 将这个迭代器适配成一个只含有那些闭包返回 true 的元素的新迭代器
        .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_my_size(shoes, 10);

    assert_eq!(
        in_my_size,
        vec![
            Shoe { size: 10, style: String::from("sneaker") },
            Shoe { size: 10, style: String::from("boot") },
        ]
    );
}

创建自定义迭代器

实现 Iterator trait
只会从 1 数到 5 的迭代器

struct Counter {
    count: u32,
}

impl Counter {
    fn new() -> Counter {
        Counter { count: 0 }
    }
}

impl Iterator for Counter {
    type Item = u32;

    fn next(&mut self) -> Option<Self::Item> {
        self.count += 1;

        if self.count < 6 {
            Some(self.count)
        } else {
            None
        }
    }
}
#[test]
fn calling_next_directly() {
    let mut counter = Counter::new();

    assert_eq!(counter.next(), Some(1));
    assert_eq!(counter.next(), Some(2));
    assert_eq!(counter.next(), Some(3));
    assert_eq!(counter.next(), Some(4));
    assert_eq!(counter.next(), Some(5));
    assert_eq!(counter.next(), None);
}

其他 Iterator trait 方法使用自定义迭代器的next

#[test]
fn using_other_iterator_trait_methods() {
    let sum: u32 = Counter::new()
        // 获取 Counter 实例产生的值
        // 将这些值与另一个 Counter 实例在省略了第一个值之后产生的值配对
        .zip(Counter::new().skip(1))
        // 将每一对值相乘
        .map(|(a, b)| a * b)
        // 只保留那些可以被3整除的结果
        .filter(|x| x % 3 == 0)
        // 将所有保留的结果相加
        .sum();
    assert_eq!(18, sum);
}

zip 只产生四对值;
第五对值 (5, None) 从未被产生
zip 在任一输入迭代器返回 None 时也返回 None文章来源地址https://www.toymoban.com/news/detail-597907.html

到了这里,关于rust学习-迭代器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Rust- 迭代器

    In Rust, an iterator is a pattern that allows you to perform some task on a sequence of items in turn. An iterator is responsible for the logic of iterating over each item and determining when the sequence has finished. In Rust, iterators are created by methods called iter() and into_iter() on collections like Vec , HashMap , etc. Rust’s iterators have a m

    2024年02月14日
    浏览(30)
  • 研读Rust圣经解析——Rust learn-11(测试,迭代器,闭包)

    测试我不打算很详细的写,大家知道如何使用其实就差不多了 一般来说我们在lib中编写测试 这样我们构建了一个test的lib 在这个工程里面你看到应该是有个lib.rs没有main.rs的 这里并不是声明一个mod,而是一个测试区域,在区域中可以写很多的测试方法 我们通过 #[cfg(test)] 宏来

    2023年04月22日
    浏览(52)
  • rust 自动化测试、迭代器与闭包、智能指针、无畏并发

    编写测试可以让我们的代码在后续迭代过程中不出现功能性缺陷问题;理解迭代器、闭包的函数式编程特性; BoxT 智能指针在堆上存储数据, RcT 智能指针开启多所有权模式等;理解并发,如何安全的使用线程,共享数据。 编写测试以方便我们在后续的迭代过程中,不会改坏

    2024年02月16日
    浏览(40)
  • 【跟小嘉学 Rust 编程】十三、函数式语言特性:迭代器和闭包

    【跟小嘉学 Rust 编程】一、Rust 编程基础 【跟小嘉学 Rust 编程】二、Rust 包管理工具使用 【跟小嘉学 Rust 编程】三、Rust 的基本程序概念 【跟小嘉学 Rust 编程】四、理解 Rust 的所有权概念 【跟小嘉学 Rust 编程】五、使用结构体关联结构化数据 【跟小嘉学 Rust 编程】六、枚举

    2024年02月11日
    浏览(60)
  • Rust编程语言入门之函数式语言特性:-迭代器和闭包

    闭包(closures) 迭代器(iterators) 优化改善 12 章的实例项目 讨论闭包和迭代器的运行时性能 闭包:可以捕获其所在环境的匿名函数。 闭包: 是匿名函数 保存为变量、作为参数 可在一个地方创建闭包,然后在另一个上下文中调用闭包来完成运算 可从其定义的作用域捕获值

    2023年04月08日
    浏览(46)
  • Rust中的迭代器的使用:map转换、filter过滤、fold聚合、chain链接

    Rust中的迭代器是一种强大的工具,它提供了一种灵活、通用的方法来遍历序列。迭代器是实现了Iterator trait的类型,并需要至少实现一个next函数,用于让迭代器指向下一个迭代对象,并返回一个Option用于指示对象是否存在。 迭代器相比于for循环有一些优势。首先,迭代器提

    2023年04月12日
    浏览(39)
  • 第八篇:强化学习值迭代及代码实现

    你好,我是郭震(zhenguo) 前几天我们学习强化学习策略迭代,今天,强化学习第8篇:强化学习值迭代 值迭代是强化学习另一种求解方法,用于找到马尔可夫决策过程(MDP)中的最优值函数。 值迭代 值迭代可以总结为如下几点: 值迭代通过不断迭代更新值函数来逼近最优值

    2024年02月08日
    浏览(44)
  • 面试之快速学习STL-迭代适配器

    参考:http://c.biancheng.net/view/7255.html 例子: 想使用反向迭代器实现逆序遍历容器,则该容器的迭代器类型必须是双向迭代器或者随机访问迭代器。 常见操作 注意这里不能用std::list,因为它是双向迭代器, +3的操作需要随机访问迭代器 。故联想到std::list排序只能使用list提供的

    2024年02月11日
    浏览(44)
  • 学习笔记-LoadRunner参数化设置及迭代配置说明

    以下内容对loadrunner进行一个初识,让之后运用更加熟练,咱们这里用的是loadrunner自带的WebTours平台,他是不含数据库的。 loadrunner的录制方式有两种,如下图所示,1:基于HTML方式(只针对鼠标和键盘事件,录制的文本比较纯净,不需要做过多筛选。)2:基于URL方式(会录制

    2023年04月15日
    浏览(55)
  • 学习adaboost(三,第二次迭代,c#实现)

    我们改进了第一次迭代:第二次迭代如下:因为三个弱分类器都是犯了3次错误,我们故意选了y6.5,标签=1,else,标签=-1;第一个弱分类器已经选了,再选一次没意义,不会有任何进展,和第一次迭代一模一样。先看代码:    float[] 第er个弱分类器jieguo = new float[] { -1, -1, -1,

    2024年02月10日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包