gpt4 book ai didi

rust - 持有Vecs的结果的高效Rust收集器

转载 作者:行者123 更新时间:2023-12-03 11:35:39 25 4
gpt4 key购买 nike

我正在学习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的目的在于静默删除错误结果,但我想以某种方式“将 flatten映射到 Result s下”。我也知道,一般来说,您无法收集类型为I的迭代器

impl Iterator<Item = Result<impl Iterator<Item = T>, Error>>

进入迭代器

Result<impl Iterator<Item = impl Iterator<Item = T>>, Error>

因为您实际上需要在外部迭代器中完成所有计算才能知道最终结果。尽管如此,当您想先 .flatten()然后又要 .collect()时,您似乎可以在这种特殊情况下完成此工作。

最后,我可以看到 collect()为我提供了一种从 it构造向量的向量的方法,然后可以将该向量展平为我想要的单个大向量。但这有许多不必要的内存分配。

标准库可以帮助您以高效的Rust-ic方式做到这一点吗?

最佳答案

我想我将从 try_fold 开始,因为它可以处理Result并停止在Err上:

fn acc2<T, E>(mut it: impl Iterator<Item = Result<Vec<T>, E>>) -> Result<Vec<T>, E> {
it.try_fold(
Vec::new(),
|mut vec, res_ts: Result<Vec<_>, E>| {
res_ts.map(move |mut ts| { // map preserves Err
// In case of Ok(...), append to already found elements
vec.append(&mut ts);
vec
})
}
)
}

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=f6f738ddedecda1875df283f221dbfdc

事实证明, Itertools已经具有 fold_results 应该可以执行您想要的操作:
fn acc3<T, E>(mut it: impl Iterator<Item = Result<Vec<T>, E>>) -> Result<Vec<T>, E> {
it.fold_results(
Vec::new(),
|mut vec, mut ts| {
vec.append(&mut ts);
vec
}
)
}

关于rust - 持有Vecs的结果的高效Rust收集器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61555907/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com