美文网首页
rust迭代器

rust迭代器

作者: Wu杰语 | 来源:发表于2024-05-18 20:04 被阅读0次

1. 函数式

rust迭代器是函数式范式实现的主体,回想一下函数式语言的几个关键特征:

  • 高阶函数:函数可以作为参数传递给其他函数,也可以作为返回值。这允许函数式程序员编写更加模块化和可重用的代码。
  • 惰性求值:函数式编程中的表达式只有在需要时才进行求值,这可以帮助提高程序的效率。
  • 函数组合:函数可以被组合在一起形成新的函数,这可以使代码更加模块化和可重用。
  • 类型系统和类型推断:函数式编程语言通常具有强大的类型系统,这可以帮助减少运行时错误和提高代码的安全性。

可以和rust实现函数式对应一下。

  • 类型系统和类型推断 -> rust的patten,match =>
  • 高阶函数 -> rust函数作为返回值,闭包
  • 函数组合 -> 迭代器map/filter..
  • 惰性求值 -> 迭代器collect/foreach..

学习rust函数式,要和Java8进行类比对比,两者实现有异曲同工。

2. rust迭代器

2.1 Iterator和IntoIterator

trait Iterator {
    type Item;
    fn next(&mut self) -> Option<Self::Item>;
    …… // 很多默认方法
}
trait IntoIterator where Self::IntoIter: Iterator<Item=Self::Item> {
    type Item;
    type IntoIter: Iterator;
    fn into_iter(self) -> Self::IntoIter;
}

Iterator和IntoIterator是迭代器的构造方法,要实现自己的迭代器,只要实现Iterator方法。例如vec的迭代器创建

let v = vec![4, 20, 12, 8, 6];
let mut iterator = v.iter();
let mut iterator1 = v.iter_mut();

iter方法创建一个迭代器,将消耗vec中的值,iter_mut创建一个迭代器,迭代取vec中值的引用。

for element in &collection { ... }
for element in &mut collection { ... }
for element in collection { ... }

for语句会自动翻译为 (&collection).into_iter(), (&mut collection).into_iter, collection.into_iter();

  • (&collection).into_iter() 会返回一个 Item 类型为 &T 的迭代器。该迭代器会生成对其条目的共享引用
  • (&mut collection).into_iter() 会返回一个 Item 类型为 &mut T的迭代器。给定对集合的可变引用,into_iter 会返回一个迭代器,该迭代器会生成对其条目的可变引用。.
  • collection.into_iter()返回迭代器,该迭代器会获取集合的所有权并按值返回这些条目,这些条目的所有权会从集合转移给消费者,原始集合在此过程中已被消耗掉了。

2.2 迭代器惰性

2.2.1 filter和map

let text = "  ponies  \n   giraffes\niguanas  \nsquid".to_string();
let v: Vec<&str> = text.lines()
    .map(str::trim)
    .filter(|s| *s != "iguanas")
    .collect();
assert_eq!(v, ["ponies", "giraffes", "squid"]);

filter 会返回第三个迭代器,它只会从 map 迭代器的结果中生成闭包 |s| *s != "iguanas" 返回 true 的那些条目

2.2.2 filter_map和flat_map

fn filter_map<B, F>(self, f: F) -> impl Iterator<Item=B>
    where Self: Sized, F: FnMut(Self::Item) -> Option<B>;
use std::str::FromStr;

let text = "1\nfrond .25  289\n3.1415 estuary\n";
for number in text
    .split_whitespace()
    .filter_map(|w| f64::from_str(w).ok())
{
    println!("{:4.2}", number.sqrt());
}

fiter_map与filter的不同是返回值是Option。

fn flat_map<U, F>(self, f: F) -> impl Iterator<Item=U::Item>
    where F: FnMut(Self::Item) -> U, U: IntoIterator;

use std::collections::HashMap;

let mut major_cities = HashMap::new();
major_cities.insert("Japan", vec!["Tokyo", "Kyoto"]);
major_cities.insert("The United States", vec!["Portland", "Nashville"]);
major_cities.insert("Brazil", vec!["São Paulo", "Brasília"]);
major_cities.insert("Kenya", vec!["Nairobi", "Mombasa"]);
major_cities.insert("The Netherlands", vec!["Amsterdam", "Utrecht"]);

let countries = ["Japan", "Brazil", "Kenya"];

for &city in countries.iter().flat_map(|country| &major_cities[country]) {
    println!("{}", city);
}

flat_map取出vec,并将vec数组展平为一个数组

2.2.3 take

fn take(self, n: usize) -> impl Iterator<Item=Self::Item>
    where Self: Sized;

fn take_while<P>(self, predicate: P) -> impl Iterator<Item=Self::Item>
    where Self: Sized, P: FnMut(&Self::Item) -> bool;

let message = "To: jimb\r\n\
               From: superego <editor@oreilly.com>\r\n\
               \r\n\
               Did you get any writing done today?\r\n\
               When will you stop wasting time plotting fractals?\r\n";
for header in message.lines().take_while(|l| !l.is_empty()) {
    println!("{}" , header);
}

take取第0-n行数据,take_while取满足predicate的数据。

2.2.4 zip

use std::iter::repeat;

let endings = ["once", "twice", "chicken soup with rice"];
let rhyme: Vec<_> = repeat("going")
    .zip(endings)
    .collect();
assert_eq!(rhyme, vec![("going", "once"),
                       ("going", "twice"),
                       ("going", "chicken soup with rice")]);

zip将两个迭代器组合成一个迭代器

2.3 迭代器求值

如果没有求值函数,则迭代器就是惰性的,不会处理。

2.3.1 count、sum 和 product

use std::io::prelude::*;

fn main() {
    let stdin = std::io::stdin();
    println!("{}", stdin.lock().lines().count());
}

count计算迭代对象个数。

2.3.2 min和max

assert_eq!([-2, 0, 1, 0, -2, -5].iter().max(), Some(&1));
assert_eq!([-2, 0, 1, 0, -2, -5].iter().min(), Some(&-5));

min和max求最大和最小值

2.3.3 any和all

let id = "Iterator";

assert!( id.chars().any(char::is_uppercase));
assert!(!id.chars().all(char::is_uppercase));

any和all表达了任意和所有的语义。

2.3.4 fold

let a = [5, 6, 7, 8, 9, 10];

assert_eq!(a.iter().fold(0, |n, _| n+1), 6);        // 计数
assert_eq!(a.iter().fold(0, |n, i| n+i), 45);       // 求和
assert_eq!(a.iter().fold(1, |n, i| n*i), 151200);   // 乘积

// 最大值
assert_eq!(a.iter().cloned().fold(i32::min_value(), std::cmp::max),
           10);

fold实现累加器

2.3.5 collection

use std::collections::;

let args: HashSet<String> = std::env::args().collect();
let args: BTreeSet<String> = std::env::args().collect();
let args: LinkedList<String> = std::env::args().collect();

// 只有键–值对才能收集到Map中,因此对于这个例子,
// 要把字符串序列和整数序列拉合在一起
let args: HashMap<String, usize> = std::env::args().zip(0..).collect();
let args: BTreeMap<String, usize> = std::env::args().zip(0..).collect();

// 其他代码略

colleciton构建集合

2.3.5 for_each

["doves", "hens", "birds"].iter()
    .zip(["turtle", "french", "calling"])
    .zip(2..5)
    .rev()
    .map(|((item, kind), quantity)| {
        format!("{} {} {}", quantity, kind, item)
    })
    .for_each(|gift| {
        println!("You have received: {}", gift);
    });

for_each遍历迭代对象

小结

rust的迭代器,对照Java8,很容易轻车熟路。学习迭代器,不要仅仅把迭代器当做一个设计模式或者rust的模块学习,要提升到函数式范式的层次来学习,这是快速掌握一门新语言的诀窍。

相关文章

  • Rust语言编程实例100题-074

    Rust语言编程实例100题-074 题目:Rust迭代器专项练习。迭代器模式是将遍历数据集合的行为抽象为单独的迭...

  • Rust语言编程实例100题-075

    Rust语言编程实例100题-075 题目:Rust迭代器专项练习。迭代器模式是将遍历数据集合的行为抽象为单独的迭...

  • Rust语言编程实例100题-076

    Rust语言编程实例100题-076 题目:Rust迭代器专项练习。迭代器模式是将遍历数据集合的行为抽象为单独的迭...

  • Rust语言编程实例100题-077

    Rust语言编程实例100题-077 题目:Rust迭代器专项练习。迭代器模式是将遍历数据集合的行为抽象为单独的迭...

  • Rust语言编程实例100题-078

    Rust语言编程实例100题-078 题目:Rust迭代器专项练习。迭代器模式是将遍历数据集合的行为抽象为单独的迭...

  • Rust for cpp devs - 迭代器

    迭代器(Iterator)可以允许对序列中的每一个元素执行某个操作。 Rust 的迭代器分为三种: iter() ...

  • rust中的迭代器

    迭代器模式,就是指对一系列项执行某些任务。 一、迭代器的作用 迭代器(iterator)负责: 1、遍历每个项2、...

  • 【RUST_BASIC】Vector 与迭代器

    1 Vector https://doc.rust-lang.org/std/vec/struct.Vec.htm...

  • RUST 学习日记 第21课 ——迭代器

    RUST 学习日记 第21课 ——迭代器(Iterator) 0x00 回顾与开篇 关于函数的学习暂时告一段落了...

  • 迭代器

    本节实验我们将为大家讲解迭代器,主要介绍 5 种常见迭代器:输入、输出迭代器,前向逆向迭代器,双向迭代器和随机迭代...

网友评论

      本文标题:rust迭代器

      本文链接:https://www.haomeiwen.com/subject/swfgfjtx.html