我正在学习Rust,并遇到了以下模式,该模式将Result<Vec<_>, _>
的迭代器折叠为一个大的Vec<_>
,如果迭代器中的任何结果失败,则会失败:
fn accumulate<T, E>(it: impl Iterator<Item = Result<Vec<T>, E>>) -> Result<Vec<T>, E> {
let mut result = Vec::new();
for mut ts in it {
result.append(&mut ts?)
}
Ok(result)
}
我想这个函数可以写成非常简短的“函数式”版本,但我一直在努力找到它。道义上来说,我想做到以下:
it.map(|v| v?.into_iter()).flatten().collect()
但这不符合类型检查。通过运行一些小例子,我认为
flatten
的目的是默默丢弃错误结果,但我希望以某种方式“在Result
下映射flatten
”。我也知道通常情况下你无法收集,比如说一个类型的迭代器。impl Iterator<Item = Result<impl Iterator<Item = T>, Error>>
转换为迭代器
Result<impl Iterator<Item = impl Iterator<Item = T>>, Error>
由于你需要在外部迭代器中完成所有计算才能知道最终结果,因此你需要这样做。然而,在特殊情况下,当你想要使用.flatten()
然后立即使用.collect()
时,似乎可以使其工作。
最后,我可以看到collect()
为我提供了一种从it
构建向量向量的方法,然后我可以将这个向量展平成我想要的单个大向量。但这会产生许多不必要的内存分配。
标准库能帮助你以高效、Rust-ic的方式完成这项任务吗?