我是Rust的新手,在文档中找不到将hashmap的值收集到向量中的方法。
假设我有一个哈希图:
score_table: HashMap<Id, Score>
我想所有的Score成Vec
all_scores: Vec<Score>
我很想使用,values但由于值不是vec,所以它不起作用:
all_scores = score_table.values()
我知道可以Values实现该ExactSizeIterator特征,但是我不知道如何将迭代器的所有值收集到向量中,而无需手动编写for循环并将向量中的值一个接一个地推入。
[编辑1]
我还尝试着use std::iter::FromIterator;降落到类似:
all_scores = Vec::from_iter(score_table.values());
Run Code Online (Sandbox Code Playgroud)
expected type `std::vec::Vec<Score>`
found type `std::vec::Vec<&Score>`
Run Code Online (Sandbox Code Playgroud)
[编辑2]
由于这个问题,我将其更改为:
all_scores = Vec::from_iter(score_table.values().cloned());
Run Code Online (Sandbox Code Playgroud)
并且不会对产生错误cargo check。
这是一个好方法吗?
Hug*_*sen 25
HashMap 上有 3 个有用的方法,它们都返回迭代器:
values()借用集合并返回引用( &T)。values_mut()提供可变引用&mut T,这对于修改集合的元素而不破坏非常有用score_table。into_values()直接给你元素:T!迭代器拥有所有元素的所有权。这意味着score_table不再拥有它们,因此您不能score_table再使用!在您的示例中,您调用values()以获取&T引用,然后T通过 a将它们转换为拥有的值clone(),这会创建可能昂贵的副本。
相反,如果我们有一个拥有值的迭代器,那么我们可以将其转换为Vecusing Iterator::collect():
let all_scores: Vec<Score> = score_table.into_values().collect();
Run Code Online (Sandbox Code Playgroud)
有时,您可能需要指定收集类型:
let all_scores = score_table.into_values().collect::<Vec<Score>>();
Run Code Online (Sandbox Code Playgroud)
Dan*_*iel 13
如果您不再需要score_table,您可以将Score值的所有权转让给all_scores:
let all_scores: Vec<Score> = score_table.into_iter()
.map(|(_id, score)| score)
.collect();
Run Code Online (Sandbox Code Playgroud)
与@apetranzilla 的克隆方法相比,这种方法会更快并且消耗更少的内存。它还支持任何结构,而不仅仅是实现Clone.
该方法Iterator.collect是为此特定任务而设计的。正确的是,您需要.cloned()一个实际值向量而不是引用(除非存储的类型实现Copy,例如基元),因此代码如下所示:
all_scores = score_table.values().cloned().collect();
Run Code Online (Sandbox Code Playgroud)
在内部,collect()仅使用FromIterator,但它也可以推断输出的类型。有时没有足够的信息来推断类型,因此您可能需要显式指定所需的类型,如下所示:
all_scores = score_table.values().cloned().collect::<Vec<Score>>();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
375 次 |
| 最近记录: |