Rust中slice.windows(2)的scan方法未执行,求非循环类替代方案
问题根源
Rust迭代器是惰性求值的——你创建了scan迭代器但没触发消费动作,所以闭包里的逻辑根本不会执行。不管用什么迭代器适配器,只要不调用消费型方法,代码都跑不起来。
解决方案
不用换迭代器方法,只要消费scan迭代器就行。既然你不想用loop或for_each,推荐这两种方式:
方式1:用fold消费迭代器
fold是标准的消费型迭代器方法,会遍历每个元素,不需要额外循环结构:
pub fn train(&mut self, sequence: &[T]) -> &mut Chain<T> { println!("4444444444444444"); sequence.windows(2).scan(1, |_state, x| { if !self.map.contains_key(&x[0]) { let mut map: HashMap<T, i32> = HashMap::new(); map.entry(x[1]).or_insert(1); self.map.insert(x[0], map); } println!("22222222"); Some(x) }).fold((), |_, _| ()); // 用fold消费迭代器,忽略结果 println!("33333333333333333"); self }
方式2:用collect消费迭代器
把迭代器收集到临时容器里(比如Vec),虽然会创建临时对象,但逻辑简单直接:
pub fn train(&mut self, sequence: &[T]) -> &mut Chain<T> { println!("4444444444444444"); let _: Vec<_> = sequence.windows(2).scan(1, |_state, x| { if !self.map.contains_key(&x[0]) { let mut map: HashMap<T, i32> = HashMap::new(); map.entry(x[1]).or_insert(1); self.map.insert(x[0], map); } println!("22222222"); Some(x) }).collect(); println!("33333333333333333"); self }
额外优化:去掉无用的scan
看你的代码里scan的state(参数1和闭包的_state)完全没用到,其实可以直接删掉scan,用fold直接处理:
pub fn train(&mut self, sequence: &[T]) -> &mut Chain<T> { println!("4444444444444444"); sequence.windows(2).fold((), |_, x| { if !self.map.contains_key(&x[0]) { let mut map: HashMap<T, i32> = HashMap::new(); map.entry(x[1]).or_insert(1); self.map.insert(x[0], map); } println!("22222222"); }); println!("33333333333333333"); self }
核心知识点
Rust迭代器分两类:
- 适配器:比如
scan、map、filter,只修改迭代器行为,不触发遍历,是惰性的。 - 消费器:比如
fold、collect、for_each,会触发遍历执行闭包逻辑。
所以只要在适配器之后调用消费器方法,代码就能正常执行。
内容的提问来源于stack exchange,提问作者jyz
相关产品推荐
相关产品推荐

