Error handling 我需要帮助重构Rust中的错误处理

Error handling 我需要帮助重构Rust中的错误处理,error-handling,rust,refactoring,rust-cargo,Error Handling,Rust,Refactoring,Rust Cargo,我想重构这个Rust代码来计算最大的系列产品,并使其尽可能高效和优雅。我觉得 lsp(string_digits: &str, span: usize) -> Result<u64, Error> 可以通过某种方式使它比现在优雅得多。lsp能否仅用一系列链式迭代器方法实现 #[derive(Debug, PartialEq)] pub enum Error { SpanTooLong, InvalidDigit(char), } fn sp(w: &

我想重构这个Rust代码来计算最大的系列产品,并使其尽可能高效和优雅。我觉得

lsp(string_digits: &str, span: usize) -> Result<u64, Error>
可以通过某种方式使它比现在优雅得多。lsp能否仅用一系列链式迭代器方法实现

#[derive(Debug, PartialEq)]
pub enum Error {
    SpanTooLong,
    InvalidDigit(char),
}

fn sp(w: &[u8]) -> u64 {
    w.iter().fold(1u64, |acc, &d| acc * u64::from(d))
}

pub fn lsp(string_digits: &str, span: usize) -> Result<u64, Error> {
    let invalid_chars = string_digits
        .chars()
        .filter(|ch| !ch.is_numeric())
        .collect::<Vec<_>>();
    if span > string_digits.len() {
        return Err(Error::SpanTooLong);
    } else if !invalid_chars.is_empty() {
        return Err(Error::InvalidDigit(invalid_chars[0]));
    } else if span == 0 || string_digits.is_empty() {
        return Ok(1);
    }

    let vec_of_u8_digits = string_digits
        .chars()
        .map(|ch| ch.to_digit(10).unwrap() as u8)
        .collect::<Vec<_>>();
    let lsp = vec_of_u8_digits
        .windows(span)
        .max_by(|&w1, &w2| sp(w1).cmp(&sp(w2)))
        .unwrap();
    Ok(sp(lsp))
}

不确定这是否是最优雅的方式,但我已经尝试过了,希望新版本与给定的程序相同

在这种情况下,需要两件事:首先,我们需要一个数据结构,它可以动态地提供滑动窗口;其次,如果转换产生错误,则需要一个函数,它可以提前结束迭代

对于前者,我选择了矢量,因为span是动态的。对于后者,有一个在itertools板条箱中调用的函数。它将结果上的迭代器转换为未包装类型上的迭代器,并在遇到错误时停止迭代

我还稍微更改了sp的签名,以接受u8上的任何迭代器

代码如下:

使用std::collections::VecDeque; 使用itertools::处理结果; [deriveDebug,PartialEq] 发布枚举错误{ 斯潘图隆, 残疾的Digitchar, } fn spw:impl迭代器->u64{ w、 fold1u64,| acc,d | acc*u64::fromd } 发布fn lspstring\u数字:&str,span:usize->Result{ 如果span>string_digits.len{ 返回ErrError::SpanTooLong; }如果span==0 | | string_digits.is_为空,则为else{ 返回Ok1; } 让mut init_state=VecDeque::new; init_state.resizespan,0; 进程\结果字符串\数字.chars .map | ch | ch.to_digit10 .map | d | d为u8 .ok_orError::InvalidDigitch, |数字| digits.scaninit_state,| state,digit|{ state.pop_back; state.push_frontdigit; Somespstate.iter.clone } 麦克斯先生 打开…的包装 }
除了要求我们检查您的代码之外,这里没有其他具体问题。这可能更适合于代码复查。@E_net4为我的行为看起来很有害而抱歉。我以前从未使用过SE的这一部分,我会确保在以后的调查中查看它。别担心,你的行为中没有有毒物质我只是关心这个问题在这个网站上的适用性。这是否回答了你的问题?这适用于大多数情况,但所有系列产品的产量为0的情况除外。例如,对于lsp99099,它将生成Ok81而不是Ok0,这是因为状态转换将是:[9]->[9,9]->[0,9,9]->[9,0,9]->[9,9,0]。解决方案是将前n个状态填充到状态之前的状态数。len==带零的范围,因此,它们的sp将始终为0,并且不会计入lsp。如下所示:if state.len==span{state.pop_back;}else{for_i in 1..span{state.push_front0u8;}},将解析后的u8数字命名为字符非常容易引起误解:是的,正确,我将更改答案以反映角落大小写和名称。