如何在不收集临时向量的情况下对结果的迭代器执行迭代器计算? [英] How do I perform iterator computations over iterators of Results without collecting to a temporary vector?
问题描述
在此示例中,我正在寻找一种消除临时向量分配的方法:
I'm looking for a way to eliminate the temporary vector allocation in this example:
fn doit<T: Iterator<Item = Result<i32, &'static str>>>(name: &str, iter: T) {
println!(
"{}: {:?}",
name,
iter.collect::<Result<Vec<_>, _>>()
.map(|v| v.into_iter().min())
);
}
fn main() {
let without_errors = vec![Ok(1), Ok(2), Ok(3)];
let with_errors = vec![Ok(1), Err("error"), Ok(2)];
doit("without errors", without_errors.into_iter());
doit("with errors", with_errors.into_iter());
}
这是 iterator的一个变体,带有错误处理主题,除了我不想创建一个集合(所以collect()
不能完全完成工作),但是我想要对要迭代的元素执行进一步的操作.
This is a variation of the iterator with error handling theme, except that I don't want to create a collection (so collect()
doesn't quite do the job), but I want to perform further operations on the elements being iterated over.
请注意,这会产生错误的结果,因为Ok
小于Err
:
Note that this gives the wrong result because Ok
is less than Err
:
fn doit<T: Iterator<Item = Result<i32, &'static str>>>(name: &str, iter: T) {
println!("{}: {:?}", name, iter.min());
}
它会偶然为max()
提供正确的结果,但不会停止对第一个错误的迭代.
It would give the right result for max()
by accident, but it would not stop iterating on the first error.
推荐答案
在此之前,我认为您唯一的选择是手动迭代(游乐场) Before that, I think your only option is manually iterating (Playground) 这篇关于如何在不收集临时向量的情况下对结果的迭代器执行迭代器计算?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!Iterator::try_fold
提供了您所需的框架,并且自Rust 1.27(
fn fold_ok<I, T, E, F>(mut iter: I, f: F) -> Result<Option<T>, E>
where
I: Iterator<Item = Result<T, E>>,
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<Item = &'r Result<i32, &'static str>> + Clone,
{
println!(
"{}: {:?}",
name,
fold_ok(iter.clone().cloned(), ::std::cmp::min)
);
}
doit("without errors", without_errors.iter());
doit("with errors", with_errors.iter());
}