如何将Rust中带终止逻辑的循环实现转换为迭代器语法?
用Rust迭代器实现十六进制数字解析函数
核心方案
要同时满足维护状态(是否开始收集数字)和提前终止迭代的需求,Rust标准库的scan迭代器适配器是最优选择——它可以携带可变状态,并且通过返回None直接终止迭代流程。
转换后的完整代码
fn parse_number<B: AsRef<str>>(input: B) -> Option<u32> { const RADIX: u32 = 16; let digits = input .as_ref() .chars() // 携带状态:是否已开始收集十六进制数字 .scan(false, |started, c| { match (*started, c.is_digit(RADIX)) { // 未开始收集且当前字符不是数字:跳过,继续迭代 (false, false) => Some(None), // 未开始收集但当前是数字:标记开始,返回该字符 (false, true) => { *started = true; Some(Some(c)) }, // 已开始收集但当前不是数字:终止迭代 (true, false) => None, // 已开始收集且当前是数字:返回该字符 (true, true) => Some(Some(c)), } }) // 过滤前导非数字阶段产生的空值,只保留有效数字字符 .flatten() // 将字符收集为字符串 .collect::<String>(); if digits.is_empty() { None } else { // 将Result转换为Option,解析失败返回None u32::from_str_radix(&digits, RADIX).ok() } }
关键逻辑解析
scan适配器的作用:- 第一个参数是初始状态
false,表示还未开始收集数字 - 闭包接收可变引用的状态变量
started和当前字符c,通过返回值控制迭代流程:Some(None):继续迭代,但不输出任何元素(对应跳过前导非数字)Some(Some(c)):继续迭代并输出字符c(对应收集有效数字)None:立即终止整个迭代(对应遇到非数字字符停止)
- 第一个参数是初始状态
flatten()的作用:将scan返回的Option<Option<char>>展平为char,过滤掉前导非数字阶段产生的空值- 最终解析:收集到的字符串为空则返回
None,否则调用from_str_radix并通过.ok()将Result转为Option
测试用例示例
fn main() { assert_eq!(parse_number(""), None); assert_eq!(parse_number("abc123def"), Some(0x123)); assert_eq!(parse_number("1a3f"), Some(0x1A3F)); assert_eq!(parse_number("xyz456ghi"), Some(0x456)); assert_eq!(parse_number("100000000"), None); // 超出u32范围 }
内容的提问来源于stack exchange,提问作者Luctins
相关产品推荐
相关产品推荐

