如何实现逆序生成偶数的Rust Iterator?修正反向步长异常
问题描述
我希望创建一个能从指定值开始逆序生成偶数的Iterator。以下Rust程序演示了当前存在的问题:该程序从命令行读取两个整数,输出它们之间的降序偶数(假设最小值为偶数)。
原代码:
use std::io::{self, BufRead}; fn main() { // Read numbers let mut input = io::BufReader::new(io::stdin()); let mut buf = String::new(); input.read_line(&mut buf).unwrap(); let mut split = buf.split(" "); let min = split.next().unwrap().trim().parse::<i64>().unwrap(); let max = split.next().unwrap().trim().parse::<i64>().unwrap(); // Attempt to generate the iterator let payload: String = (min..max) .rev() .step_by(2) .map(|x| x.to_string() + " ") .collect(); println!("{payload}"); }
当输入2 6时,程序输出5 3,而预期结果应为4 2(正序迭代可生成2 4)。请问如何实现能得到正确结果的Iterator?
问题分析与解决方案
原因分析
原代码的核心问题在于左闭右开区间的逆序逻辑:
- 正序时
2..6生成的是2,3,4,5,过滤偶数后得到2,4,符合预期。 - 调用
.rev()后,区间会逆转为5,4,3,2,再通过.step_by(2)取数时,会从5开始每隔2个取一个,最终得到5,3,完全偏离了目标偶数序列。
可行解决方案
方法1:调整区间起点,生成正确的逆序偶数序列
先计算区间内最大的有效偶数(因为max是开区间,实际上限是max-1,如果是奇数则减1转为偶数,偶数直接使用),再基于调整后的区间生成逆序序列:
use std::io::{self, BufRead}; fn main() { let mut input = io::BufReader::new(io::stdin()); let mut buf = String::new(); input.read_line(&mut buf).unwrap(); let mut split = buf.split(" "); let min = split.next().unwrap().trim().parse::<i64>().unwrap(); let max = split.next().unwrap().trim().parse::<i64>().unwrap(); // 计算区间内最大的偶数 let max_even = if (max - 1) % 2 == 0 { max - 1 } else { max - 2 }; let payload: String = (min..=max_even) .rev() .step_by(2) .map(|x| format!("{x} ")) .collect(); println!("{payload}"); }
方法2:先过滤偶数再逆序(简单直观)
先在正序区间中过滤出所有偶数,再将结果逆序,这种方法逻辑简单易懂,适合快速实现:
use std::io::{self, BufRead}; fn main() { let mut input = io::BufReader::new(io::stdin()); let mut buf = String::new(); input.read_line(&mut buf).unwrap(); let mut split = buf.split(" "); let min = split.next().unwrap().trim().parse::<i64>().unwrap(); let max = split.next().unwrap().trim().parse::<i64>().unwrap(); let payload: String = (min..max) .filter(|&x| x % 2 == 0) .rev() .map(|x| format!("{x} ")) .collect(); println!("{payload}"); }
方法3:手动实现逆序偶数迭代器(自定义逻辑)
如果需要更灵活的控制,可以手动实现一个符合需求的Iterator,这种方式适合需要复用该迭代逻辑的场景:
use std::io::{self, BufRead}; use std::iter::Iterator; // 自定义逆序偶数迭代器 struct DescendingEven { current: i64, min: i64, } impl Iterator for DescendingEven { type Item = i64; fn next(&mut self) -> Option<Self::Item> { if self.current < self.min { None } else { let result = self.current; self.current -= 2; Some(result) } } } // 生成迭代器的构造函数 fn descending_even(min: i64, max: i64) -> DescendingEven { let start = if (max - 1) % 2 == 0 { max - 1 } else { max - 2 }; DescendingEven { current: start, min } } fn main() { let mut input = io::BufReader::new(io::stdin()); let mut buf = String::new(); input.read_line(&mut buf).unwrap(); let mut split = buf.split(" "); let min = split.next().unwrap().trim().parse::<i64>().unwrap(); let max = split.next().unwrap().trim().parse::<i64>().unwrap(); let payload: String = descending_even(min, max) .map(|x| format!("{x} ")) .collect(); println!("{payload}"); }
验证结果
以上三种方法在输入2 6时,都会输出4 2,完全符合预期。
内容的提问来源于stack exchange,提问作者vahvero
相关产品推荐
相关产品推荐

