我正在实现一个集合类型,它包含一个结构体的向量。我想实现一系列方法来以各种方式对向量进行排序。每个函数返回一个值的集合是很重要的,因为调用点会进一步修改结果,这可能意味着删除或更改值,并且这些更改都不应该传播回原始集合。
结构体非常基本:
#[derive(PartialEq, Debug, Clone)]
pub struct Shoe {
size: u32,
style: String,
}
集合类型只是将结构体 Package 到一个向量中,如下所示:
#[derive(Debug, PartialEq, Clone)]
pub struct ShoesInventory {
shoes: Vec<Shoe>
}
我想根据给定的尺寸过滤所有现有的鞋子,并将结果作为一个单独的向量返回。基本上,迭代、过滤和收集。然而,当我写这段代码时,
impl ShoesInventory {
pub fn new(shoes: Vec<Shoe>) -> ShoesInventory {
ShoesInventory { shoes }
}
pub fn shoes_in_size(&self, shoe_size: u32) -> Vec<Shoe> {
self.shoes.iter().filter(| s| s.size == shoe_size).collect()
}
}
我得到了以下编译器错误
error[E0277]: a value of type `Vec<Shoe>` cannot be built from an iterator over elements of type `&Shoe`
--> src/shoes.rs:18:9
|
18 | self.shoes.iter().filter(| s| s.size == shoe_size).collect()
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
| |
| value of type `Vec<Shoe>` cannot be built from `std::iter::Iterator<Item=&Shoe>`
|
= help: the trait `FromIterator<&Shoe>` is not implemented for `Vec<Shoe>`
如果我试图克隆闭包中的元素,它不会修复任何东西,我仍然会得到同样的错误,不清楚问题是什么,在另一个向量上b/c这个代码模式实际上是有效的,例如,当你使用另一个具有原始类型的向量,比如integer,迭代器,Map/过滤器,收集模式就可以正常工作。
let v1: Vec<i32> = vec![1, 2, 3];
let v2: Vec<_> = v1.iter().map(|x| x + 1).collect(); // no problem here
然而,当向量元素包含一个结构体或字符串时,事情就变得棘手了。
我知道这个错误基本上是说,fromIterator没有实现,但是为什么呢?我该如何修复这个错误呢?
Playground code
1条答案
按热度按时间zvokhttg1#
你告诉Rust你想返回一个
Vec<Shoe>
--即一个拥有的shoe对象的集合,但是你却给它提供了一个shoe的引用序列。根据这个函数的用例,至少有几个方向可以选择。
只要这个函数的调用者实际上并不需要拥有的鞋子,那么你就可以把这个函数改为:
调用者将收到一个vec,其中包含对满足过滤条件的shoe的引用,这通常正是您想要的--如果不需要,为什么要做
Shoe
结构体的昂贵克隆呢?注意,rust编译器将自动确保返回的引用的生存期不超过它们所引用的
ShoeInventory
的生存期。通常情况下,如果满足以下条件之一,您 * 可能 * 希望返回拥有的项目:
在这两种情况下,克隆它们可能更合适,就像你在评论中指出的那样,在这种情况下,我会在过滤后克隆它们,这样你就不会克隆项目然后立即丢弃它们: