Rust 迭代器

111 阅读3分钟

在 Rust 中,迭代器(Iterator)是一种用于遍历集合元素的抽象概念,它提供了一种统一且高效的方式来处理各种数据结构。下面从多个方面详细介绍 Rust 迭代器。

基本概念

迭代器是实现了 Iterator trait 的类型。Iterator trait 定义了一个核心方法 next,该方法用于依次返回集合中的元素,当没有更多元素时返回 None

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

这里 Item 是迭代器返回元素的类型,next 方法是迭代器的核心,通过不断调用 next 可以遍历集合中的元素。

创建迭代器

Rust 中许多集合类型都实现了 IntoIterator trait,这意味着它们可以通过 into_iteriteriter_mut 方法转换为迭代器。

  • iter 方法:返回一个不可变引用的迭代器,适用于只读遍历。
fn main() { 
    let numbers = vec![1, 2, 3, 4, 5]; 
    let iter = numbers.iter(); 
    for num in iter { 
        println!("{}", num); } 
    } 
  • iter_mut 方法:返回一个可变引用的迭代器,适用于需要修改集合元素的情况。
    let mut numbers = vec![1, 2, 3, 4, 5]; 
    let iter = numbers.iter_mut(); 
    for num in iter { 
        *num *= 2; 
    } 
    println!("{:?}", numbers); 
} 
  • into_iter 方法:将集合的所有权转移到迭代器中,迭代器会消耗集合元素。
fn main() { 
    let numbers = vec![1, 2, 3, 4, 5]; 
    let iter = numbers.into_iter(); 
    for num in iter { 
        println!("{}", num); 
    } 
    // 下面这行代码会报错,因为 numbers 的所有权已经转移 
    // println!("{:?}", numbers); 
} 

迭代器适配器

迭代器适配器是一类方法,它们可以对迭代器进行转换或操作,返回一个新的迭代器。常见的迭代器适配器有:

  • map:对迭代器中的每个元素应用一个闭包,返回一个新的迭代器。
fn main() { 
    let numbers = vec![1, 2, 3, 4, 5]; 
    let squared: Vec<i32> = numbers.iter().map(|x| x * x).collect(); 
    println!("{:?}", squared); 
} 
  • filter:根据闭包的返回值过滤迭代器中的元素,只保留满足条件的元素。
fn main() { 
    let numbers = vec![1, 2, 3, 4, 5]; 
    let even_numbers: Vec<i32> = numbers.iter().filter(|x| x % 2 == 0).cloned().collect(); 
    println!("{:?}", even_numbers); 
} 
  • take:只取迭代器中的前 n 个元素。
fn main() { 
    let numbers = vec![1, 2, 3, 4, 5]; 
    let first_two: Vec<i32> = numbers.iter().take(2).cloned().collect(); 
    println!("{:?}", first_two); 
} 

消费器方法

消费器方法会消耗迭代器并返回一个最终结果。常见的消费器方法有:

  • collect:将迭代器的元素收集到一个集合中,如 VecHashMap 等。
fn main() { 
    let numbers = vec![1, 2, 3, 4, 5]; 
    let squared: Vec<i32> = numbers.iter().map(|x| x * x).collect(); 
    println!("{:?}", squared); 
} 
  • sum:计算迭代器中所有元素的和。
fn main() { 
    let numbers = vec![1, 2, 3, 4, 5]; 
    let total: i32 = numbers.iter().sum(); 
    println!("Total: {}", total); 
} 
  • fold:使用一个初始值和一个闭包对迭代器中的元素进行累积计算。
fn main() { 
    let numbers = vec![1, 2, 3, 4, 5]; 
    let product: i32 = numbers.iter().fold(1, |acc, x| acc * x); 
    println!("Product: {}", product); 
} 

自定义迭代器

除了使用标准库提供的迭代器,你还可以自定义迭代器。要自定义迭代器,需要实现 Iterator trait。

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> { 
        if self.count < 5 { 
            self.count += 1; 
            Some(self.count) 
        } else {
            None 
        } 
    } 
} 

fn main() { 
    let counter = Counter::new(); 
    for num in counter { 
        println!("{}", num); 
    } 
} 

在这个例子中,我们定义了一个 Counter 结构体,并为其实现了 Iterator trait,从而创建了一个自定义的迭代器。

总结

Rust 迭代器是一种强大且灵活的工具,它提供了统一的方式来遍历和操作集合元素。通过迭代器适配器和消费器方法,我们可以高效地处理数据,同时 Rust 的所有权和借用规则确保了迭代器的使用是安全的。自定义迭代器则允许我们根据具体需求创建自己的迭代逻辑。