如何将Result流转为Vec的Result?避免多次into_iter和collect操作
一步完成流的错误处理与元素转换
当然可以一步完成所有操作,而且有两种更简洁高效的实现方式,避免中间生成多余的Vec:
方式一:先收集合法元素再转换
利用StreamExt::try_collect直接将Stream<Item=Result<Thing, ()>>转换为Result<Vec<Thing>, ()>,然后链式处理元素过滤与收集:
use futures::stream::StreamExt; struct Thing { key: Option<i32>, } async fn _unused(stream: impl futures::Stream<Item = Result<Thing, ()>>) -> Result<Vec<i32>, ()> { Ok( stream .try_collect::<Vec<_>>()? .into_iter() .filter_map(|o| o.key) .collect() ) }
方式二:流处理阶段直接完成转换(更高效)
在流的每个元素处理阶段就完成错误处理、Optional值过滤,最后直接收集结果。这种方式无需先存储所有Thing实例,内存占用更低,且遇到错误会立即返回,无需处理后续元素:
use futures::stream::StreamExt; struct Thing { key: Option<i32>, } async fn _unused(stream: impl futures::Stream<Item = Result<Thing, ()>>) -> Result<Vec<i32>, ()> { stream .and_then(|thing| async move { Ok(thing.key) }) .filter_map(|opt_key| opt_key) .collect() .await }
原代码的问题
原代码通过两次collect生成了两个中间Vec(Vec<Result<Thing, ()>>和Vec<Thing>),不仅增加了内存开销,还多了一次迭代过程。上面的两种方式都避免了多余的中间结构,代码更简洁,性能也更优。
内容的提问来源于stack exchange,提问作者Max Heiber
相关产品推荐
相关产品推荐

