gpt4 book ai didi

rust - Rayon 折叠成一个 HashMap

转载 作者:行者123 更新时间:2023-11-29 08:28:30 57 4
gpt4 key购买 nike

我有一个 Vec<Result<MyStruct, ()>> ,我想将它们放入 HashMap 中的桶中,其中键是 MyStruct.b field 和 values 是一个包含所有 MyStructs 的 Vec MyStruct.b领域(见下面的 Playground 链接,可能更清楚)。我正在使用折叠,它适用于普通的 .fold

let my_array = vec![Ok(m1), Ok(m2), Ok(m3), Err(())];

let result: HashMap<String, Vec<&MyStruct>> = my_array
.iter()
.filter_map(|value| value.as_ref().ok())
.fold(HashMap::new(), |mut acc, value| {
acc.entry(value.b.clone()).or_insert(vec![]).push(&value);
acc
});

但是,我无法用人造丝实现同样的效果

let my_array = vec![Ok(m1), Ok(m2), Ok(m3), Err(())];

let result = my_array
.par_iter()
.filter_map(|value| value.as_ref().ok())
.fold(
||HashMap::new(),
|mut acc, value| {
acc.entry(value.b.clone()).or_insert(vec![]).push(&value);
acc
}
)
.collect::<HashMap<String, Vec<&MyStruct>>>();

我得到的错误是

   Compiling playground v0.0.1 (/playground)
error[E0277]: the trait bound `std::collections::HashMap<std::string::String, std::vec::Vec<&MyStruct>>: rayon::iter::FromParallelIterator<std::collections::HashMap<std::string::String, std::vec::Vec<&&MyStruct>>>` is not satisfied
--> src/main.rs:39:10
|
39 | .collect::<HashMap<String, Vec<&MyStruct>>>();
| ^^^^^^^ the trait `rayon::iter::FromParallelIterator<std::collections::HashMap<std::string::String, std::vec::Vec<&&MyStruct>>>` is not implemented for `std::collections::HashMap<std::string::String, std::vec::Vec<&MyStruct>>`
|
= help: the following implementations were found:
<std::collections::HashMap<K, V, S> as rayon::iter::FromParallelIterator<(K, V)>>

Playground

最佳答案

根据 parallel fold documentation :

The parallel fold works similarly except that it first breaks up your list into sublists, and hence instead of yielding up a single sum at the end, it yields up multiple sums. The number of results is nondeterministic, as is the point where the breaks occur.

所以你想reducefold的结果变成一个值作为最终结果,而不是collect:

let result = my_array
.par_iter()
.filter_map(|value| value.as_ref().ok())
.fold(
|| HashMap::new(),
|mut acc, value| {
acc.entry(value.b.clone()).or_insert(vec![]).push(value);
acc
},
)
.reduce(
|| HashMap::new(),
|m1, m2| {
m2.iter().fold(m1, |mut acc, (k, vs)| {
acc.entry(k.clone()).or_insert(vec![]).extend(vs);
acc
})
},
);

OTOH :

reduce() requires that the identity function has the same type as the things you are iterating over, and it fully reduces the list of items into a single item

所以你可以一次性reduce到最终结果:

let result = my_array
.par_iter()
.filter_map(|value| value.as_ref().ok())
.map(|s| {
let mut m = HashMap::new();
m.insert(s.b.clone(), vec![s]);
m
})
.reduce(
|| HashMap::new(),
|m1, m2| {
m2.iter().fold(m1, |mut acc, (k, vs)| {
acc.entry(k.clone()).or_insert(vec![]).extend(vs);
acc
})
},
);

选择fold or map/reduce由您决定。

关于rust - Rayon 折叠成一个 HashMap,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57641821/

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