如何在Rust中实现或获取迭代器的按元素扩展链式方法?
在Rust中扩展迭代器元素的简洁实现
标准库自带方案:flat_map
直接用标准库的Iterator::flat_map就能满足需求,它会将每个元素映射为一个子迭代器,再把所有子迭代器的元素扁平合并成新迭代器,完全支持链式调用,无需额外依赖:
fn main() { let numbers = vec![10, 20, 30]; let result: Vec<i32> = numbers .iter() .flat_map(|&x| [x, x + 1, x + 2]) // 用数组字面量生成子迭代器,无额外内存分配 .collect(); assert_eq!(result, vec![10, 11, 12, 20, 21, 22, 30, 31, 32]); }
如果需要动态生成元素(比如数量不固定),可以用std::iter::once链式调用构建子迭代器:
use std::iter::once; fn main() { let numbers = vec![10, 20, 30]; let result: Vec<i32> = numbers .iter() .flat_map(|&x| once(x).chain(once(x + 1)).chain(once(x + 2))) .collect(); }
自定义expand方法(完全匹配你的预期写法)
如果你偏好示例中通过闭包往容器push元素的expand接口,可以自己实现一个Iterator扩展trait,底层封装flat_map逻辑:
trait ExpandIterator: Iterator { fn expand<F>(self, f: F) -> impl Iterator<Item = Self::Item> where F: Fn(Self::Item, &mut Vec<Self::Item>), { self.flat_map(|item| { let mut container = Vec::new(); f(item, &mut container); container.into_iter() }) } } // 为所有迭代器实现该trait impl<I: Iterator> ExpandIterator for I {} fn main() { let numbers = vec![10, 20, 30]; let result: Vec<i32> = numbers .into_iter() // 若用iter(),需配合copied()/cloned()获取元素所有权 .expand(|x, container| { container.push(x); container.push(x + 1); container.push(x + 2); }) .collect(); assert_eq!(result, vec![10, 11, 12, 20, 21, 22, 30, 31, 32]); }
现成crate方案
如果不想自己实现,itertools crate提供了丰富的迭代器工具,其中的flat_map与标准库功能一致,还包含batching等辅助方法可间接实现类似需求。但针对你的核心需求,标准库的flat_map已经足够简洁高效。
内容的提问来源于stack exchange,提问作者Illumin
相关产品推荐
相关产品推荐

