详解Rust标准库:迭代器

查看本地官方文档

安装rust后运行

rustup doc

查看The Standard Library即可获取标准库内容

迭代器是什么

迭代器是一种检查容器内元素并遍历元素的数据类型

创建迭代器

创建迭代器有三种方式,标准库中的大多数类型可以实现其中的一个或三个

  • iter():迭代不可变引用所有权&T
  • iter_mut():迭代可变引用所有权&mut T
  • into_iter():创建一个拥有所有权的迭代器T,原集合的所有权被转移到迭代器将无法使用

iter()

fn main() {
    let vec = vec![1, 2, 3];
    for item in vec.iter() {
        println!("{}", item);
    }
    // 所有权仍然属于 vec
    for item in vec.iter() {
        println!("{}", item);
    }
}

iter_mut()

fn main() {
    let mut vec = vec![1, 2, 3];
    for item in vec.iter_mut() {
        *item += 1;
    }
    for item in vec.iter() {
        println!("{}", item);
    }
}

into_iter()

fn main() {
    let vec = vec![1, 2, 3];
    for item in vec.into_iter() {
        println!("{}", item);
    }
    // 所有权被转移到 for 循环中,离开作用域被drop,无法再次使用
    // for item in vec.into_iter() {
    //     println!("{}", item);
    // }
}

for循环

迭代器和for看起来功能相同

fn main() {
    let vec = vec![1,2,3,4,5,6];    // for 循环遍历
    for num in vec{
        println!("{}",num);
    }
    println!("----------------------------------------");
    let vec = vec![1,2,3,4,5,6];
    // iterator 迭代器遍历
    for num in vec.iter(){
        println!("{}",num);
    }
}

for in循环是一个语法糖,for in可以遍历所有实现trait std::iter::IntoIterator的类型(即转换为迭代器的类型),直到 .into_iter() 返回的迭代器返回 None (或循环体使用 break)

std::iter::IntoIterator定义

pub trait IntoIterator {
    type Item;
    // IntoIter的类型是一个迭代器
    type IntoIter: Iterator<Item = Self::Item>;

    // 必须的方法
    fn into_iter(self) -> Self::IntoIter;
}

type Item定义了一个关联类型,表示这个类型可以产生的元素类型;type IntoIter: Iterator<Item = Self::Item>定义了一个关联类型,这个类型必须实现了Iteratortrait,产生的元素类型必须与Item类型相同;fn into_iter(self) -> Self::IntoIter所有实现了IntoIteratortrait的类型作为参数传进来可以返回一个类型为IntoIter的迭代器

总的来说,IntoIterator定义了一种公共的行为,对于实现了IntoIteratortrait的类型可以将其转换为迭代器

由于vec实现了IntoIterator中的IntoIter行为,我们可以通过以下方法将vec转换为迭代器

fn main() {
    let v = [1, 2, 3];
    let mut iter = v.into_iter();
    
    println!("{:?}", iter.next());//Somne(1)
    println!("{:?}", iter.next());//Some(2)
    println!("{:?}", iter.next());//Some(3)
}

迭代器中的.next()方法是惰性的,只有在调用它时才会返回下一个Option<>枚举包含的值

对于以下for in代码

for loop_variable in iterator {
    code()
}

for in会被解析为以下内容,IntoIterator::into_iter将返回一个迭代器,通过loop循环不断调用迭代器的.next()方法,但.next()方法返回None时结束循环,当返回Some()时继续执行code()中编写的内容

{
    let result = match IntoIterator::into_iter(iterator) {
        mut iter => loop {
            match iter.next() {
                None => break,
                Some(loop_variable) => { code(); },
            };
        },
    };
    result
}

如何实现自己的迭代器

迭代器trait定义

pub trait Iterator {
    type Item;
    fn next(&mut self) -> Option<Self::Item>;
}

type Item定义了一个关联类型,用于表示迭代器产生的元素类型;Option<>枚举类型返回Some()None

// 自定义类型
struct MyStruct {
    data: Vec<i32>,
}
// 为自定义类型实现方法
impl MyStruct {
    fn new() -> Self {
        MyStruct { data: vec![1, 2, 3] }
    }
}
struct MyIterator {
    index: usize,
    data: Vec<i32>,
}
// 为自定义类型实现迭代器
impl Iterator for MyIterator {
    // 定义迭代器返回类型
    type Item = i32;
    // 实现迭代器 next 方法
    fn next(&mut self) -> Option<Self::Item> {
        if self.index < self.data.len() {
            let value = self.data[self.index];
            self.index += 1;
            Some(value)
        } else {
            None
        }
    }
}
// 为自定义类型实现 IntoIterator trait,用于将自定义类型转换为迭代器
impl IntoIterator for MyStruct {
    type Item = i32;
    type IntoIter = MyIterator;
    // 实现 IntoIterator trait 的 into_iter 方法,调用此方法将自定义类型转换为迭代器
    fn into_iter(self) -> Self::IntoIter {
        MyIterator { index: 0, data: self.data }
    }
}
fn main() {
    let my_struct = MyStruct::new();
    // 使用 into_iter 方法将 my_struct 转换为迭代器
    let mut my_iter = my_struct.into_iter();
    println!("{}", my_iter.next().unwrap()); // 1
    println!("{}", my_iter.next().unwrap()); // 2
    println!("{}", my_iter.next().unwrap()); // 3
}

这里我们通过调用迭代器的.next()方法惰性的获取自定义类型的下一个值,由于返回的值是Some(item),通过unwrap()可以将其解包出来

使用以下{:?}可以打印出它的原始内容

    println!("{:?}", my_iter.next()); // Some(1)
    println!("{:?}", my_iter.next()); // Some(2)
    println!("{:?}", my_iter.next()); // Some(3)

由于for in语法糖可以遍历所有实现了IntoIterator的类型,可以直接通过for in调用IntoIterator::into_iter方法,它将返回一个迭代器Iterator并调用使用loop方法调用迭代器的.next()方法

fn main() {
    let my_struct = MyStruct::new();
    // 使用 into_iter 方法将 my_struct 转换为迭代器
    for item in my_struct {
        println!("{}", item);
    }
}

迭代器适配器

常用方法

map:映射,对迭代器中的每个元素映射一个函数,然后返回一个新的迭代器,新迭代器中的元素是原元素经过映射函数转换后的结果

fn main() {
    let vec = vec![1, 2, 3, 4, 5, 6];
    // 将 vec 转换为迭代器,并使用 map 函数将每个元素乘以 2,并收集结果到一个新向量中
    let doubled_numbers: Vec<_> = vec
        .iter()
        .map(|&num| num * 2)
        .collect();
    println!("{:?}", doubled_numbers);
    // [2, 4, 6, 8, 10, 12]
}

take:获取,从迭代器中获取指定数量的元素,然后返回一个新的迭代器

fn main() {
    let vec = vec![1, 2, 3, 4, 5, 6];
    // 获取第二个到第四个元素并且收集到vec中
    let second_to_fourth: Vec<_> = vec.iter().skip(1).take(3).collect();
    println!("{:?}", second_to_fourth);
    // [2, 3, 4]
}

filter:过滤,根据给定的条件过滤迭代器中的元素

fn main() {
    let vec = vec![1, 2, 3, 4, 5, 6];
    // 过滤偶数
    let even_number: Vec<_> = vec
        .iter()
        .filter(|&num| num % 2 == 0)
        .collect();
    println!("even_number: {:?}", even_number);
    // even_number: [2, 4, 6]
}

collect:将迭代器中的元素收集到一个特定的数据结构中,如向量、哈希表等

fn main() {
    let vec = vec![1, 2, 3];
    let collected_vec: Vec<_> = vec.iter().collect();
    println!("{:?}", collected_vec);
    // [1, 2, 3]
}

将数据收集到hash map中

use std::collections::HashMap;
fn main() {
    let vec = vec![1, 2, 3];
    // 将 vec中的数据映射处理后手收集到HashMap<i32, i32>
    let hash_map: HashMap<i32, i32> = vec
        .iter()
        .map(|&x| (x, x * 2))
        .collect();
    println!("{:?}", hash_map);
    // {3: 6, 1: 2, 2: 4}
}

skip:跳过迭代器中的指定数量的元素

fn main() {
    let vec = vec![1, 2, 3, 4, 5, 6];
    let skipped = vec.iter().skip(2).collect::<Vec<_>>();
    println!("Skipped elements: {:?}", skipped);
    // Skipped elements: [3, 4, 5, 6]
}

其他方法

size_hint:返回一个迭代器剩余元素数量可能值的下限和上限的提示,返回一个元组 (lower_bound, upper_bound)lower_bound 是迭代器中剩余元素数量的最小可能值,upper_bound 是迭代器中剩余元素数量的最大可能值。对于很多标准的迭代器,这两个值通常是相等的,尤其是当迭代器的长度是已知的时候。size_hint主要用于优化,例如为迭代器的元素保留空间

fn main() {
    let vec = vec![1, 2, 3];
    let iter = vec.iter();
    let (lower, upper) = iter.size_hint();
    println!("Lower bound: {}, Upper bound: {}", lower, upper.unwrap());
    // Lower bound: 3, Upper bound: 3
}

count:计算迭代器中元素的数量

fn main() {
    let vec = vec![1, 2, 3];
    let count = vec.iter().count();
    println!("Number of elements: {}", count);
    // Number of elements: 3
}

last:返回迭代器中的最后一个元素,如果迭代器为空则返回None

fn main() {
    let vec = vec![1, 2, 3];
    let last_element = vec.iter().last();
    println!("Last element: {:?}", last_element);
    // Last element: Some(3)

    let last_element: Option<&i32> = vec.iter().last();
    println!("Last element: {:?}", last_element);
    // Last element: None
}

nth:返回迭代器中指定位置的元素,如果位置超出范围则返回None

fn main() {
    let vec = vec![1, 2, 3];
    let third_element = vec.iter().nth(2);
    println!("Third element: {:?}", third_element);
    // Third element: Some(3)

    let fourth_element = vec.iter().nth(3);
    println!("Fourth element: {:?}", fourth_element);
    // Fourth element: None
}

step_by:以指定的步长从迭代器中获取元素

fn main() {
    let vec = vec![1, 2, 3, 4, 5, 6];
    let step_by_two = vec.iter().step_by(2).collect::<Vec<_>>();
    println!("Elements at step 2: {:?}", step_by_two);
    // Elements at step 2: [1, 3, 5]
}

chain:连接两个或多个迭代器,依次产生它们的元素

fn main() {
    let vec1 = vec![1, 2];
    let vec2 = vec![3, 4];
    let chained = vec1.iter().chain(vec2.iter()).collect::<Vec<_>>();
    println!("Chained elements: {:?}", chained);
    // Chained elements: [1, 2, 3, 4]
}

zip:将两个迭代器的元素压缩成一个元组迭代器

fn main() {
    let vec1 = vec![1, 2];
    let vec2 = vec![3, 4];
    let zipped = vec1.iter().zip(vec2.iter()).collect::<Vec<_>>();
    println!("Zipped elements: {:?}", zipped);
    // Zipped elements: [(1, 3), (2, 4)]
}

for_each:对迭代器中的每个元素应用一个闭包函数,不返回任何值

fn main() {
    let vec = vec![1, 2, 3];
    vec.iter().for_each(|x| println!("Element: {}", x));
    // Element: 1
    // Element: 2
    // Element: 3
}

filter_map:对迭代器中的每个元素映射一个函数,该映射函数返回一个Option类型。如果映射函数返回Some,则将该值放入新的迭代器中;如果返回None,则丢弃该元素

fn main() {
    let vec = vec![1, 2, 3];
    let filtered_mapped = vec
        .iter()
        .filter_map(|x| if x % 2 == 0 { Some(x * 2) } else { None })
        .collect::<Vec<_>>();
    println!("Filtered and mapped elements: {:?}", filtered_mapped);
    // Filtered and mapped elements: [4]
}

enumerate:为迭代器中的每个元素生成一个索引和元素的元组

fn main() {
    let vec = vec![1, 2, 3];
    let enumerated = vec.iter().enumerate().collect::<Vec<_>>();
    println!("Enumerated elements: {:?}", enumerated);
    // Enumerated elements: [(0, 1), (1, 2), (2, 3)]
}

peekable:创建一个可以 “窥视” 下一个元素的迭代器,查看下一个元素而不消耗它

fn main() {
    let vec = vec![1, 2, 3];
    let mut peekable_iter = vec.iter().peekable();
    // 先打印下一个元素而不消耗它
    if let Some(&element) = peekable_iter.peek() {
        println!("Peeked element: {}", element);
        // Peeked element: 1
    }

    // 再打印所有元素,证明之前的 peek 没有消耗元素
    for element in peekable_iter {
        println!("Iterated element: {}", element);
        // Iterated element: 1
        // Iterated element: 2
        // Iterated element: 3
    }
}

skip_while:跳过迭代器中的元素,直到谓词函数返回false

fn main() {
    let vec = vec![1, 2, 3, 4, 5, 6];
    let skipped = vec
        .iter()
        .skip_while(|x| *x < &3)
        .collect::<Vec<_>>();
    println!("Skipped elements: {:?}", skipped);
    // Skipped elements: [3, 4, 5, 6]
}

take_while:从迭代器中获取元素,直到谓词函数返回false

fn main() {
    let vec = vec![1, 2, 3, 4, 5, 6];
    let taken = vec
        .iter()
        .take_while(|x| *x < &3)
        .collect::<Vec<_>>();
    println!("Taken elements: {:?}", taken);
    // Taken elements: [1, 2]
}

map_while:类似filter_map,遇到None不会停止而是yield让步,对迭代器中的每个元素映射一个闭包函数,返回Option类型,有值返回Some()没值返回None

fn main() {
    let vec = [-1i32, 4, 0, 1];
    let mut iter = vec.iter().map_while(|x| (16i32).checked_div(*x));
    println!("{:?}", iter.next());// Some(-16)
    println!("{:?}", iter.next());// Some(4)
    println!("{:?}", iter.next());// None
    println!("{:?}", iter.next());// Some(16)
}

map_whiletake_while区别map_while第一次遇到None后停止映射,尝试将 16 除以当前元素。如果除法操作成功,会返回Some(result);如果当前元素为 0 导致除法错误,checked_div()返回Some(result)表示除法成功,否则返回Nonetake_while只保留那些结果为Some的元素,一旦遇到第一个None就停止迭代,map对结果进行解包,提取出实际的整数值

fn main() {
    let vec = [-1i32, 4, 0, 1];
    let mut iter = vec
        .iter()
        .map(|x| (16i32).checked_div(*x))
        .take_while(|x| x.is_some())
        .map(|x| x.unwrap());
    println!("{:?}", iter.next());// Some(-16)
    println!("{:?}", iter.next());// Some(4)
    println!("{:?}", iter.next());// None
    println!("{:?}", iter.next());// None
}

map_while一旦闭包返回None,后续的元素将不会被处理

fn main() {
    let vec = [1, 2, -3, 4, 5, -6, 7, 8];
    let mut iter = vec.iter();
    // by_ref()将迭代器中的元素借用,不会消耗元素
    // map_while对迭代器中的每个元素应用一个闭包函数,u32::try_from(*n).ok()尝试将当前元素从i32转换为u32类型,如果转换成功则返回Some(u32),否则返回None
    // map_while会将返回Some的元素收集起来,而忽略返回None的元素
    // collect()将处理后的迭代器收集成一个Vec<u32>类型的向量
    let result: Vec<u32> = iter
        .by_ref()
        .map_while(|n| u32::try_from(*n).ok())
        .collect();

    println!("{:?}", result);
    // [1, 2]

    // 由于-3没有转换为u32类型,所以map_while会忽略它,其后的被放回迭代器
    let result: Vec<i32> = iter.cloned().collect();
    println!("{:?}", result);
    // [4, 5, -6, 7, 8]
}

不够优雅,-6遇到不能转换的就停止了,我们可以使用filter_map,可以看到使用filter_map会将原来的元素消耗掉,map_while不同的是,即使某个元素导致闭包返回None,后续的元素仍然会被继续处理

fn main() {
    let vec = [1, 2, -3, 4, 5, -6, 7, 8];
    let mut iter = vec.iter();
    let result: Vec<u32> = iter.by_ref().filter_map(|n| u32::try_from(*n).ok()).collect();
    println!("{:?}", result);
    // [1, 2, 4, 5, 7, 8]
    let result: Vec<i32> = iter.cloned().collect();
    println!("{:?}", result);
    // []
}

scan:对迭代器中的元素进行累积计算,并返回每一步的中间结果

fn main() {
    let vec = vec![1, 2, 3];
    // 第一个参数是初始状态,第二个参数是闭包函数,返回值是 Option<T>
    let scanned = vec
        .iter()
        .scan(1, |state, x| {
            *state += x;
            Some(*state)
        })
        .collect::<Vec<_>>();
    println!("Scanned elements: {:?}", scanned);
    // Scanned elements: [2, 4, 7]
}

flat_map:对迭代器中的每个元素映射一个函数,该映射函数返回一个迭代器,然后将这些迭代器的元素扁平化到一个新的迭代器中

fn main() {
    let vec = vec![vec![1, 2], vec![3, 4]];
    let flattened = vec
        .iter()
        .flat_map(|inner_vec| inner_vec.iter())
        .collect::<Vec<_>>();
    println!("Flattened elements: {:?}", flattened);
    // Flattened elements: [1, 2, 3, 4]
}

flatten:如果迭代器的元素是嵌套的迭代器,将它们扁平化到一个新的迭代器中。通常用于处理嵌套的结构

fn main() {
    let nested_vec = vec![vec![1, 2], vec![3, 4]];
    let flattened = nested_vec.iter().flatten().collect::<Vec<_>>();
    println!("Flattened elements: {:?}", flattened);
    // Flattened elements: [1, 2, 3, 4]
}

fuse:创建一个 “熔断” 的迭代器,一旦迭代器被耗尽,后续的迭代操作将立即返回None,而不是再次尝试从源迭代器中获取元素

fn main() {
    let vec = vec![1, 2, 3];
    let mut fused_iter = vec.iter().fuse();
    for _ in 0..4 {
        if let Some(element) = fused_iter.next() {
            println!("Element: {}", element);
            // Element: 1
            // Element: 2
            // Element: 3
        } else {
            println!("Iteration exhausted.");
            // Iteration exhausted.
        }
    }
}

inspect:对迭代器中的每个元素引用并应用一个闭包函数,不改变、不消耗元素,用于调试或记录目的

fn main() {
    let vec = vec![1, 2, 3];
    let inspected = vec
        .iter()
        .inspect(|x| println!("Inspecting element: {}", x))
        .collect::<Vec<_>>();
    // Inspecting element: 1
    // Inspecting element: 2
    // Inspecting element: 3

    // 没有消耗元素,仍然可以使用
    println!("Collected elements: {:?}", inspected);
    // Collected elements: [1, 2, 3]
}

by_ref:获取迭代器的可变引用,允许在不转移所有权的情况下对迭代器进行可变操作

fn main() {
    let mut vec = vec![1, 2, 3];
    // 可变操作
    let iter = vec.iter_mut();
    iter.for_each(|x| {
        *x *= 2;
        println!("Modified element: {}", x);
        // Modified element: 2
        // Modified element: 4
        // Modified element: 6
    });
    // 所有权没转移,所以 vec 还可以使用
    println!("Final vector: {:?}", vec);
    // Final vector: [2, 4, 6]
}

partition:根据给定的谓词函数将迭代器中的元素分为两个部分,分别放入两个不同的容器中

fn main() {
    let vec = vec![1, 2, 3, 4];
    // 偶数元素和奇数元素的分割
    let (even, odd): (Vec<&i32>, Vec<&i32>) = vec.iter().partition(|x| *x % 2 == 0);
    println!("Even elements: {:?}", even.into_iter().collect::<Vec<_>>());
    // Even elements: [2, 4]
    println!("Odd elements: {:?}", odd.into_iter().collect::<Vec<_>>());
    // Odd elements: [1, 3]
}

fold:对迭代器中的元素进行累积计算,从一个初始值开始,依次应用一个函数

fn main() {
    let vec = vec![1, 2, 3];
    // 将元素累加,第一个参数是初始值,第二个参数是一个闭包函数
    let sum = vec.iter().fold(1, |acc, x| acc + x);
    println!("Sum: {}", sum);
    // Sum: 7
}

try_fold:类似于fold,对迭代器中的元素进行累积计算,从一个初始值开始,依次应用一个函数,但可以在处理过程中返回错误

fn main() {
    let vec = vec![1, 2, 3];
    // 将元素累加,初始值为 1,返回值类型为 Option<T>,错误返回Err,成功返回Ok
    let sum_result = vec.iter().try_fold(1, |acc, x| {
        if *x > 10 { Err("Value too large") } else { Ok(acc + x) }
    });
    println!("Sum result: {:?}", sum_result);
    // Sum result: Ok(7)
}

reduce:对迭代器中的元素进行归约操作,与fold类似,但没有初始值,对一个迭代器中的元素进行累积计算,将其缩减为一个单一的值

fn main() {
    let reduced: i32 = (1..10).reduce(|acc, e| acc + e).unwrap();
    println!("Reduced: {}", reduced);
    // Reduced: 45

    // 相当于fold的用法
    let folded: i32 = (1..10).fold(0, |acc, e| acc + e);
    println!("Folded: {}", folded);
    // Folded: 45
}

all:判断迭代器中的所有元素是否都满足给定的谓词函数

fn main() {
    let vec = vec![2, 4, 6];
    // 判断所有元素是否都是偶数
    let all_even = vec.iter().all(|x| *x % 2 == 0);
    println!("All elements are even: {}", all_even);
    // All elements are even: true
}

any:判断迭代器中是否至少有一个元素满足给定的谓词函数

fn main() {
    let vec = vec![1, 2, 3];
    // 判断是否有一个元素是偶数
    let any_even = vec.iter().any(|x| *x % 2 == 0);
    println!("Any element is even: {}", any_even);
    // Any element is even: true
}

find:在迭代器中查找满足给定谓词函数的第一个元素,如果找到则返回Some,否则返回None

fn main() {
    let vec = vec![1, 2, 3];
    let found_element = vec.iter().find(|x| **x == 2);
    println!("Found element: {:?}", found_element);
    // Found element: Some(2)
}

find_map:对迭代器中的每个元素映射一个函数,该映射函数返回一个Option类型。如果函数返回Some,则将该值作为结果返回;如果返回None,则继续查找下一个元素

fn main() {
    let vec = vec![1, 2, 3];
    let found_mapped_element = vec.iter().find_map(|x| if x % 2 == 0 { Some(x * 2) } else { None });
    println!("Found mapped element: {:?}", found_mapped_element);
    // Found mapped element: Some(4)
}

position:在迭代器中查找满足给定谓词函数的元素的位置,如果找到则返回Some,否则返回None

fn main() {
    let vec = vec![1, 2, 3];
    let position = vec.iter().position(|x| *x == 2);
    println!("Position of element 2: {:?}", position);
    // Position of element 2: Some(1)
}

rposition:从迭代器的末尾开始查找满足给定谓词函数的元素的位置,如果找到则返回Some,否则返回None

fn main() {
    let vec = vec![1, 2, 3, 4, 5, 6];
    // rposition 反向查找元素2的索引
    let a = vec
        .iter()
        .rposition(|&x| x == 2)
        .unwrap();
    println!("{}", a);
    // 1
}

max:返回迭代器中的最大元素,如果迭代器为空则返回None

fn main() {
    let vec = vec![1, 2, 3];
    let max_element = vec.iter().max();
    println!("Max element: {:?}", max_element);
    // Max element: Some(3)
}

min:返回迭代器中的最小元素,如果迭代器为空则返回None

fn main() {
    let vec = vec![1, 2, 3];
    let min_element = vec.iter().min();
    println!("Min element: {:?}", min_element);
    // Min element: Some(1)
}

max_by_key:根据给定的键提取函数,返回迭代器中的具有最大键值的元素,如果迭代器为空则返回None

fn main() {
    let vec = vec![("apple", 3), ("banana", 5), ("cherry", 2)];
    // 指定key为第一个元素,找字符最长的值
    let max_by_length = vec.iter().max_by_key(|&(s, _)| s.len());
    println!("Max by key: {:?}", max_by_length);
    // Max by key: Some(("cherry", 2))
}

max_by:根据给定的比较函数,返回迭代器中的最大元素,如果迭代器为空则返回None

fn main() {
    let vec = vec![1, 2, 3];
    // cmp(a,b)比较两个值,a<b返回Less = -1,a==b返回Equal = 0,a>b返回Greater = 1
    let max_by_custom = vec.iter().max_by(|a, b| a.cmp(b));
    println!("Max by custom: {:?}", max_by_custom);
    // Max by custom: Some(3)
}

min_by_key:根据给定的键提取函数,返回迭代器中的具有最小键值的元素,如果迭代器为空则返回None

fn main() {
    let vec = vec![("apple", 3), ("banana", 5), ("cherry", 2)];
    // 找长度最小的元素
    let min_by_length = vec.iter().min_by_key(|&(s, _)| s.len());
    println!("Min by key: {:?}", min_by_length);
    // Min by key: Some(("apple", 3))
}

min_by:根据给定的比较函数,返回迭代器中的最小元素,如果迭代器为空则返回None

fn main() {
    let vec = vec![1, 2, 3];
    let min_by_custom = vec.iter().min_by(|a, b| a.cmp(b));
    println!("Min by custom: {:?}", min_by_custom);
    // Min by custom: Some(1)
}

rev:反转迭代器中的元素顺序

fn main() {
    let vec = vec![1, 2, 3];
    let reversed = vec.iter().rev().collect::<Vec<_>>();
    println!("Reversed elements: {:?}", reversed);
    // Reversed elements: [3, 2, 1]
}

unzip:如果迭代器中的元素是元组,将其拆分为两个迭代器,一个包含元组的第一个元素,另一个包含元组的第二个元素

fn main() {
    let tuples = vec![(1, 'a'), (2, 'b'), (3, 'c')];
    // 映射后克隆元素,然后解构
    let (numbers, chars): (Vec<i32>, Vec<char>) = tuples
        .iter()
        .cloned()
        .map(|(n, c)| (n, c))
        .unzip();
    println!("Numbers: {:?}", numbers);
    // Numbers: [1, 2, 3]
    println!("Chars: {:?}", chars);
    // Chars: ['a', 'b', 'c']
}

copied:对于迭代器中可复制的元素,创建一个新的迭代器,其中每个元素都是原元素的副本

fn main() {
    let vec = vec![String::from("hello"), String::from("world")];
    let copied_iter = vec.iter().cloned().collect::<Vec<String>>();
    println!("Copied elements: {:?}", copied_iter);
    // Copied elements: ["hello", "world"]
}

cloned:类似于copied,但更通用,对于实现了Clone trait 的元素进行克隆,创建一个新的迭代器

fn main() {
    let vec = vec![Box::new(1), Box::new(2)];
    let cloned_iter = vec.iter().cloned().collect::<Vec<_>>();
    println!("Cloned elements: {:?}", cloned_iter);
    // Cloned elements: [1, 2]
}

cycle:创建一个无限循环的迭代器,重复产生原迭代器中的元素

fn main() {
    let vec = vec![1, 2, 3];
    let mut cycled_iter = vec.iter().cycle();
    // 生产6个元素后停止循环
    for _ in 0..6 {
        if let Some(element) = cycled_iter.next() {
            println!("Element: {}", element);
        }
    }
}
// Element: 1
// Element: 2
// Element: 3
// Element: 1
// Element: 2
// Element: 3

sum:计算迭代器中所有元素的总和,要求元素实现std::iter::Sum trait

fn main() {
    let vec = vec![1, 2, 3];
    let total_sum = vec.iter().sum::<i32>();
    println!("Sum: {}", total_sum);
    // Sum: 6
}

product:计算迭代器中所有元素的乘积,要求元素实现std::iter::Product trait

fn main() {
    let vec = vec![2, 3, 4];
    let total_product = vec.iter().product::<i32>();
    println!("Product: {}", total_product);
    // Product: 24
}

cmp严格比较两个迭代器的每一个元素,要求两个迭代器的长度相同,如果长度不同,程序会发生panic,返回一个std::cmp::Ordering值,表示它们的相对顺序,cmp(a,b)比较两个值,a<b返回Less = -1a==b返回Equal = 0a>b返回Greater = 1根据每个元素返回的Ordering值判断两个数组的大小

以下例子前两个元素返回Equal,第三个元素返回Less,所以vec1更小,长度相同时每个元素的结果可以反映整个数组总和的大小

fn main() {
    let vec1 = vec![1, 2, 3];
    let vec2 = vec![1, 2, 4];
    let comparison = vec1.iter().cmp(vec2.iter());
    println!("Comparison result: {:?}", comparison);
    // Comparison result: Less
}

partial_cmp:部分比较两个迭代器中的元素,不要求两个迭代器的长度相同,返回一个Option<std::cmp::Ordering>值,先根据长度相同的部分比较,不同的部分有值则比另一个大

以下例子虽然vec2总和比vec1大,但前两个元素一个返回Greater一个返回Lessvec1存在第三个元素返回Greater,所以vec1更大

fn main() {
    let vec1 = vec![2, 3, 4];
    let vec2 = vec![1, 10];
    let partial_comparison = vec1.iter().partial_cmp(vec2.iter());
    println!("Partial comparison result: {:?}", partial_comparison);
    // Partial comparison result: Some(Greater)
}

eq:判断两个迭代器中的元素是否相等,要求元素实现std::cmp::Eq trait 和std::hash::Hash trait

fn main() {
    let vec1 = vec![1, 2, 3];
    let vec2 = vec![1, 2, 3];
    let are_equal = vec1.iter().eq(vec2.iter());
    println!("Are equal: {}", are_equal);
    // Are equal: true
}

ne:判断两个迭代器中的元素是否不相等,要求元素实现std::cmp::Eq trait 和std::hash::Hash trait

fn main() {
    let vec1 = vec![1, 2, 3];
    let vec2 = vec![1, 2, 4];
    let are_not_equal = vec1.iter().ne(vec2.iter());
    println!("Are not equal: {}", are_not_equal);
    // Are not equal: true
}

lt:判断一个迭代器中的元素是否都小于另一个迭代器中的对应元素,要求元素实现std::cmp::PartialOrd trait

fn main() {
    let vec1 = vec![1, 2, 3];
    let vec2 = vec![2, 3, 4];
    let is_less_than = vec1.iter().lt(vec2.iter());
    println!("Is less than: {}", is_less_than);
    // Is less than: true
}

gt:判断一个迭代器中的元素是否都大于另一个迭代器中的对应元素,要求元素实现std::cmp::PartialOrd trait

fn main() {
    let vec1 = vec![2, 3, 4];
    let vec2 = vec![1, 2, 3];
    let is_greater_than = vec1.iter().gt(vec2.iter());
    println!("Is greater than: {}", is_greater_than);
    // Is greater than: true
}

ge:判断一个迭代器中的元素是否都大于等于另一个迭代器中的对应元素,要求元素实现std::cmp::PartialOrd trait

fn main() {
    let vec1 = vec![2, 3, 3];
    let vec2 = vec![1, 2, 3];
    let is_greater_than_or_equal = vec1.iter().ge(vec2.iter());
    println!("Is greater than or equal: {}", is_greater_than_or_equal);
    // Is greater than or equal: true
}

is_sorted:判断迭代器中的元素是否已按升序排序

fn main() {
    let vec = vec![1, 2, 3];
    let is_sorted_result = vec.iter().is_sorted();
    println!("Is sorted: {}", is_sorted_result);
    //  Is sorted: true
}

is_sorted_by:根据给定的比较函数判断迭代器中的元素是否已排序

// a <= b 返回 true,否则返回 false
fn custom_cmp(a: &i32, b: &i32) -> bool {
    *a <= *b
}
fn main() {
    let vec = vec![5, 3, 8, 2, 7];
    let is_sorted_result = vec
        .iter()
        .cloned()
        .collect::<Vec<i32>>()
        .is_sorted_by(|a, b| custom_cmp(a, b));
    println!("Is sorted: {}", is_sorted_result);
}

is_sorted_by_key:根据给定的键提取函数判断迭代器中的元素是否已按键排序

fn main() {
    let vec = vec![("apple", 3), ("banana", 5), ("cherry", 2)];
    // 判断是否按照 key 的长度进行排序
    let is_sorted_result = vec.iter().is_sorted_by_key(|&(s, _)| s.len());
    println!("Is sorted by key length: {}", is_sorted_result);
    // Is sorted by key length: true
}

夜间的实验性 API:在rust 1.82.0 中的实验性API,当你读到这篇文章的时候可能已经完善了

安装Rust nightly到项目文件夹

rustup override set nightly

切换到夜间发布版

rustup default nightly

切换回稳定版

rustup default stable

查看当前默认版本

rustup show

查看默认工具链

rustup toolchain list

next_chunk:推进迭代器并返回包含下一个值的数组,如果没有足够的元素来填充数组,则迭代器返回Err并包含剩余元素

#![feature(iter_next_chunk)]
fn main() {
    let mut iter = "lorem".chars();
    println!("{:?}", iter.next_chunk::<2>().unwrap());
    // ['l', 'o']
    println!("{:?}", iter.next_chunk::<3>().unwrap());
    // ['r', 'e', 'm']
}

next_chunk依据空白分割字符串,获取每一个单词

#![feature(iter_next_chunk)]
fn main() {
    let quote = "not all those who wander are lost";
    // 依据空白分割字符串,获取每一个单词
    let [first, second, third] = quote.split_whitespace().next_chunk().unwrap();
    println!("{} : {} : {}", first, second, third);
    // not : all : those
}

advance_by:将迭代器向前移动指定的步数,如果无法移动足够的步数,则返回剩余需要移动的步数或者在错误情况下返回错误值

#![feature(iter_advance_by)]
fn main() {
    let vec = vec![1, 2, 3, 4];
    let mut iter = vec.iter();
    let _ = iter.advance_by(2);
    println!("{:?}", iter.next()); // Some(3)
    println!("{:?}", iter.next()); // Some(4)
    println!("{:?}", iter.next()); // None
}

eq_by:判断两个迭代器中的元素是否在经过指定的函数处理后相等

#![feature(iter_order_by)]
fn main() {
    let vec1 = vec![1, 2, 3];
    let vec2 = vec![1, 2, 4];
    // 判断vec1和vec2每一个元素取模后是否相等
    let are_equal = vec1.iter().eq_by(vec2.iter(), |a, b| a % 2 == b % 2);
    println!("Are equal by modulo 2: {}", are_equal);
    // Are equal by modulo 2: false
}

intersperse:在迭代器的元素之间插入一个给定的值,返回一个新的迭代器

#![feature(iter_intersperse)]
fn main() {
    let vec = vec![1, 2, 3];
    // 向迭代器中插入元素0
    let interspersed = vec.iter().intersperse(&0).collect::<Vec<_>>();
    println!("Interspersed elements: {:?}", interspersed);
    // Interspersed elements: [1, 0, 2, 0, 3]
}

intersperse_with:与intersperse类似,但插入的值是通过一个闭包函数生成的

#![feature(iter_intersperse)]
fn main() {
    let vec = vec![1, 2, 3];
    let interspersed = vec
        .iter()
        .intersperse_with(|| &0)
        .collect::<Vec<_>>();
    println!("Interspersed elements with generated value: {:?}", interspersed);
    // Interspersed elements with generated value: [1, 0, 2, 0, 3]
}

map_windows:对迭代器中的连续元素窗口应用一个映射函数,返回一个新的迭代器,其中包含映射后的窗口结果

#![feature(iter_map_windows)]
fn main() {
    let vec = vec![1, 2, 3, 4];
    // 以固定3个元素为窗口,克隆并计算每个窗口的和,1+2+3=6,2+3+4=9
    let mapped_windows = vec
        .iter()
        .map_windows(|w: &[&i32; 3]| w.iter().cloned().sum::<i32>())
        .collect::<Vec<_>>();
    println!("Mapped windows: {:?}", mapped_windows);
    // Mapped windows: [6, 9]
}

try_collect:类似于collect,将迭代器中的元素收集到一个特定的数据结构中,如向量、哈希表等,但在收集过程中可以返回错误

#![feature(iterator_try_collect)]
use std::fmt::Error;
fn main() {
    let vec = vec![1, 2, 3];
    let result: Result<Vec<i32>, Error> = Ok(Vec::<i32>::from_iter(vec.iter().cloned()));
    println!("Try collect result: {:?}", result);
    // Try collect result: Ok([1, 2, 3])
}

collect_into:将迭代器中的元素收集到一个已存在的可写入的目标容器中

#![feature(iter_collect_into)]
fn main() {
    let vec1 = vec![1, 2, 3];
    let mut vec2:Vec<u8> = Vec::new();
    // 将 vec1 i32元素收集到 vec2 u8中
    vec1.iter().collect_into(&mut vec2);
    println!("Collected into: {:?}", vec2);
    // Collected into: [1, 2, 3]
}

partition_in_place:根据给定的闭包条件对数组进行原地分区,查找谓词函数计算的第一个设置为false的元素和最后一个计算结果设置为为true的最后一个元素,并重复交换它们

其实就是双指针法

  1. 维护两个指针,一个指向已处理部分的末尾(通常初始时指向数据结构的开头),另一个用于遍历整个数据结构
  2. 遍历指针逐个检查元素。如果当前元素满足闭包中的条件,就将其与已处理部分末尾指针指向的元素交换位置,然后将已处理部分的末尾指针向后移动一位
  3. 重复这个过程,直到遍历指针到达数据结构的末尾

时间复杂度:O(n)

#![feature(iter_partition_in_place)]
fn main() {
    let mut vec = vec![1, 2, 3, 4, 6, 7, 8];
    // 根据给定的闭包条件对数组进行原地分区,满足条件(偶数)的元素在前面,不满足条件(奇数)的元素在后面,并返回分区点的索引
    let middle = vec.iter_mut().partition_in_place(|&x| x % 2 == 0);
    // 打印分区点的索引和两个分区的元素
    println!("Middle index: {}", middle);
    // Middle index: 4
    println!("Even numbers: {:?}", &vec[..middle]);
    // Even numbers: [8, 2, 6, 4]
    println!("Odd numbers: {:?}", &vec[middle..]);
    // Odd numbers: [3, 7, 1]
}

is_partitioned:判断一个迭代器中的元素是否已经按照给定的谓词进行了分区

#![feature(iter_is_partitioned)]
fn main() {
    let vec = vec![2, 4, 1, 3];
    let is_even = |x: &i32| *x % 2 == 0;
    let is_partitioned_result = vec.iter().is_partitioned(is_even);
    println!("Is partitioned: {}", is_partitioned_result);
    // Is partitioned: true
}

try_reduce:类似于reduce,对迭代器中的元素进行累积计算,没有初始值(对于只有一个元素的迭代器将第一个元素作为初始值),依次应用一个函数,但可以在处理过程中返回错误

#![feature(iterator_try_reduce)]
fn main() {
    let numbers: Vec<usize> = vec![1, 2, 3, 4, 5];
    let sum = numbers
        .into_iter()
        .try_reduce(|x, y| x.checked_add(y))
        .unwrap();
    println!("Sum: {:?}", sum.unwrap());
    // Sum: 15

    let numbers = vec!["1", "2", "3", "4", "5"];
    let max: Result<Option<_>, <usize as std::str::FromStr>::Err> = numbers
        .into_iter()
        .try_reduce(|x, y| {
            if x.parse::<usize>()? > y.parse::<usize>()? { Ok(x) } else { Ok(y) }
        });
    println!("Try reduce result: {:?}", max.unwrap());
    // Try reduce result: Some("5")
}

try_find:在迭代器中查找满足给定谓词的第一个元素,如果找到则返回Some,否则返回Err,仅支持实现了std::ops::Trytrait的类型

#![feature(try_find)]
fn main() {
    let vec = ["1", "2", "lol", "NaN", "5"];
    let is_my_num = |s: &str, search: i32| -> Result<bool, std::num::ParseIntError> {
        Ok(s.parse::<i32>()? == search)
    };
    // 尝试查找 vec 中等于 2 的数字
    let result = vec.iter().try_find(|&&s| is_my_num(s, 2));
    println!("{:?}", result);
    // Ok(Some("2"))

    // 尝试查找 vec 中等于 5 的数字
    let result = vec.iter().try_find(|&&s| is_my_num(s, 5));
    println!("{:?}", result);
    // Err(ParseIntError { kind: InvalidDigit })
}

array_chunks:将迭代器中的元素分割成固定大小的数组块,返回一个新的迭代器

#![feature(iter_array_chunks)]
fn main() {
    let vec = vec![1, 2, 3, 4, 5];
    // 分成 2 个一组
    let chunks = vec.iter().array_chunks::<2>();
    for chunk in chunks {
        println!("Chunk: {:?}", chunk);
    }
}

cmp_by:使用指定的比较函数比较两个迭代器中的元素,返回一个std::cmp::Ordering值,表示它们的相对顺序

#![feature(iter_order_by)]
fn main() {
    let vec1 = vec![1, 2, 3];
    let vec2 = vec![1, 2, 4];
    let comparison = vec1.iter().cmp_by(vec2.iter(), |a, b| a.cmp(b));
    println!("Comparison by custom function: {:?}", comparison);
    // Comparison by custom function: Less
}

partial_cmp_by:部分比较两个迭代器中的元素,使用指定的比较函数,返回一个Option<std::cmp::Ordering>

#![feature(iter_order_by)]
fn main() {
    let vec1 = vec![1, 2, 3];
    let vec2 = vec![1, 2, 4];
    let partial_comparison = vec1.iter().partial_cmp_by(vec2.iter(), |a, b| Some(a.cmp(b)));
    println!("Partial comparison by custom function: {:?}", partial_comparison);
    // Partial comparison by custom function: Some(Less)
}

eq_by:判断两个迭代器中的元素是否在经过指定的函数处理后相等

#![feature(iter_order_by)]
fn main() {
    let vec1 = vec![1, 2, 3];
    let vec2 = vec![1, 4, 9];
    let are_equal = vec1.iter().eq_by(&vec2, |&x, &y| x * x == y);
    println!("Are equal by custom function: {}", are_equal);
    // Are equal by custom function: true
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

cci497

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值