请求重构Rust代码:优化最大序列乘积与错误处理实现
没问题!咱们来重构这段Rust代码,让它更高效、优雅,并且完全用链式迭代器实现lsp函数。先看看原代码可以优化的地方:两次遍历字符串检查无效字符+转换数字、冗余的sp函数、unwrap()可能引发panic,还有滑动窗口乘积计算可以更紧凑。
下面是重构后的代码,我会逐段解释优化点:
#[derive(Debug, PartialEq)] pub enum Error { SpanTooLong, InvalidDigit(char), } pub fn lsp(string_digits: &str, span: usize) -> Result<u64, Error> { // 先处理边界情况:span为0或空字符串直接返回1 if span == 0 || string_digits.is_empty() { return Ok(1); } // 一次遍历完成:字符转u8数字+无效字符错误处理 let digits = string_digits .chars() .map(|c| { c.to_digit(10) .map(|d| d as u8) .ok_or_else(|| Error::InvalidDigit(c)) }) .collect::<Result<Vec<u8>, Error>>()?; // 检查span是否超出字符串长度 if span > digits.len() { return Err(Error::SpanTooLong); } // 链式迭代器完成滑动窗口乘积计算+找最大值 digits .windows(span) // 优化:如果窗口包含0,直接返回0,避免多余乘法计算 .map(|window| { if window.contains(&0) { 0 } else { window.iter().fold(1u64, |acc, &d| acc * u64::from(d)) } }) .max() // 理论上不会走到这里,因为前面已经确保span <= digits.len() .ok_or(Error::SpanTooLong) }
核心优化点:
- 合并遍历与错误处理:原代码先遍历一次收集无效字符,再遍历一次转数字,现在用
map结合ok_or_else,一次遍历完成转换和错误检查,减少了一次O(n)遍历。 - 移除冗余函数:把
sp函数的逻辑直接内联到迭代器的map中,代码更紧凑直观。 - 避免panic风险:原代码中
ch.to_digit(10).unwrap()和.unwrap()都可能引发panic,现在所有潜在错误都通过Result处理,更安全。 - 链式迭代器风格:从
digits.windows(span)开始,用map计算乘积、max找最大值,整个流程完全链式调用,符合Rust的函数式编程风格。 - 乘积计算优化:提前检查窗口中的0,直接返回0,避免不必要的乘法运算,尤其是当span较大时能提升效率。
测试验证
比如输入lsp("1234", 2),会返回Ok(12)(3*4);输入lsp("abc", 2)会返回Err(Error::InvalidDigit('a'));输入lsp("12", 3)会返回Err(Error::SpanTooLong),和原代码的行为完全一致,但更高效优雅。
内容的提问来源于stack exchange,提问作者Ahmed Tawfeeq
相关产品推荐
相关产品推荐

