How do I perform iterator computations over iterators of Results without collecting to a temporary vector?

后端 未结 3 873
忘了有多久
忘了有多久 2020-12-02 02:21

I\'m looking for a way to eliminate the temporary vector allocation in this example:

fn doit>         


        
3条回答
  •  隐瞒了意图╮
    2020-12-02 03:19

    Iterator::try_fold provides the framework for what you need, and it's available since Rust 1.27 (Playground):

    fn fold_ok(mut iter: I, f: F) -> Result, E>
    where
        I: Iterator>,
        T: Ord,
        F: Fn(T, T) -> T,
    {
        iter.try_fold(None, |r, i| {
            let i = i?;
            Ok(Some(if let Some(r) = r { f(r, i) } else { i }))
        })
    }
    
    fn main() {
        let without_errors = vec![Ok(1), Ok(2), Ok(3)];
        let with_errors = vec![Ok(1), Err("error"), Ok(2)];
    
        fn doit<'r, T>(name: &str, iter: T)
        where
            T: Iterator> + Clone,
        {
            println!("{}: {:?}", name, fold_ok(iter.cloned(), ::std::cmp::min));
        }
    
        doit("without errors", without_errors.iter());
        doit("with errors", with_errors.iter());
    }
    

    Before that, I think your only option is manually iterating (Playground)

    fn fold_ok(mut iter: I, f: F) -> Result, E>
    where
        I: Iterator>,
        T: Ord,
        F: Fn(T, T) -> T,
    {
        let mut result = match iter.next() {
            None => return Ok(None),
            Some(r) => r?,
        };
    
        for item in iter {
            result = f(result, item?);
        }
    
        Ok(Some(result))
    }
    
    fn main() {
        let without_errors = vec![Ok(1), Ok(2), Ok(3)];
        let with_errors = vec![Ok(1), Err("error"), Ok(2)];
    
        fn doit<'r, T>(name: &str, iter: T)
        where
            T: Iterator> + Clone,
        {
            println!(
                "{}: {:?}",
                name,
                fold_ok(iter.clone().cloned(), ::std::cmp::min)
            );
        }
    
        doit("without errors", without_errors.iter());
        doit("with errors", with_errors.iter());
    }
    

提交回复
热议问题