我试图过滤一个Vec<Vocabulary>,其中Vocabulary是一个自定义struct,它本身包含一个struct VocabularyMetadata和一个Vec<Word>:

#[derive(Serialize, Deserialize)]
pub struct Vocabulary {
    pub metadata: VocabularyMetadata,
    pub words: Vec<Word>
}

这是用于处理web应用程序中的路由,其中路由如下所示:/word/<vocabulary_id>/<word_id>.

下面是我当前try 在Vec<Vocabulary>中输入的代码:

let the_vocabulary: Vec<Vocabulary> = vocabulary_context.vocabularies.iter()
    .filter(|voc| voc.metadata.identifier == vocabulary_id)
    .collect::<Vec<Vocabulary>>();

这行不通.我得到的错误是:

 the trait `std::iter::FromIterator<&app_structs::Vocabulary>` is not implemented for `std::vec::Vec<app_structs::Vocabulary>` [E0277]

我不知道如何实现任何FromIterator,也不知道为什么这是必要的.在同一个web应用程序的另一条路径中,同一个文件我执行以下操作:

let result: Vec<String> = vocabulary_context.vocabularies.iter()
    .filter(|voc| voc.metadata.identifier.as_str().contains(vocabulary_id))
    .map(encode_to_string)
    .collect::<Vec<String>>();
    result.join("\n\n")  // returning

所以String代表FromIterator.

然而,我不明白,为什么我不能简单地从filtercollect方法中得到Vec的元素.

我怎样才能在我的Vec中输入filter,然后简单地得到Vec<Vocabulary>中的元素,条件为真?

推荐答案

学习如何创建一个minimal, reproducible examplevery important编程技巧.你的问题可以归结为:

struct Vocabulary;

fn main() {
    let numbers = vec![Vocabulary];
    let other_numbers: Vec<Vocabulary> = numbers.iter().collect();
}

让我们看看您 case 的错误消息:

error[E0277]: a collection of type `std::vec::Vec<Vocabulary>` cannot be built from an iterator over elements of type `&Vocabulary`
 --> src/main.rs:5:57
  |
5 |     let other_numbers: Vec<Vocabulary> = numbers.iter().collect();
  |                                                         ^^^^^^^ a collection of type `std::vec::Vec<Vocabulary>` cannot be built from `std::iter::Iterator<Item=&Vocabulary>`
  |
  = help: the trait `std::iter::FromIterator<&Vocabulary>` is not implemented for `std::vec::Vec<Vocabulary>`

这意味着Vec<Vocabulary>不能由&Vocabulary的迭代器生成.你看到区别了吗?你有一个引用的迭代器(&),not一个值的迭代器.Vec如何知道如何将引用转换为值?


你怎么修?我不知道在你的情况下什么最有效:

  1. 不要迭代引用,而是迭代值本身.默认 Select 要求您拥有向量的所有权.使用into_iter而不是iter:

    let the_vocabulary: Vec<Vocabulary> = vocabulary_context
        .vocabularies
        .into_iter()
        .filter(|voc| voc.metadata.identifier == vocabulary_id)
        .collect();
    

    如果有可变引用,也可以使用迭代器:

    let the_vocabulary: Vec<Vocabulary> = vocabulary_context
        .vocabularies
        .drain(..)
        .filter(|voc| voc.metadata.identifier == vocabulary_id)
        .collect();
    
  2. 通过克隆来复制对象.这要求您正在迭代的类型实现Clone.如果你将其与过滤配对,你应该在过滤之后和拨打collect()之前拨打cloned(),以避免克隆你丢弃的东西.

    let the_vocabulary: Vec<Vocabulary> = vocabulary_context
        .vocabularies
        .iter()
        .filter(|voc| voc.metadata.identifier == vocabulary_id)
        .cloned()
        .collect();
    
  3. 不要收集值,收集Vec个引用.这就要求,无论您以后如何使用这些项目,您都可以通过引用而不是通过值获取项目:

    let the_vocabulary: Vec<&Vocabulary> = vocabulary_context
        .vocabularies
        .iter()
        .filter(|voc| voc.metadata.identifier == vocabulary_id)
        .collect();
    

注意,我删除了冗余的类型说明符(collect上的turbofish ::<>).您只需要在collect上指定变量或的类型,而不是两者都指定.实际上,这三个示例都可以从let the_vocabulary: Vec<_>开始,让编译器根据迭代器推断集合中的类型.这是惯用的风格,但为了演示,我保留了显式类型.


另见:

Rust相关问答推荐

如何处理对打包字段的引用是未对齐错误?

为什么对不可复制数据的引用的取消引用没有O权限来避免Rust中的双重释放?

为什么复印是豆荚的一个重要特征?

关于Rust 中回归的逻辑

自定义结果枚举如何支持`?`/`FromResidual`?

在IntoIter上调用.by_ref().Take().rev()时会发生什么情况

Rust函数的返回值不能引用局部变量或临时变量

习语选项<;T>;到选项<;U>;当T->;U用From定义

如何轮询 Pin>?

处理带有panic 的 Err 时,匹配臂具有不兼容的类型

.在 Rust 模块标识符中

使用在功能标志后面导入的类型,即使未启用功能标志

在 Rust 中实现资源消耗的安全包装器

打印 `format_args!` 时borrow 时临时值丢失

无法理解 Rust 对临时值的不可变和可变引用是如何被删除的

Rust 中函数的类型同义词

我如何将特征作为 struct 的拥有字段?

在 Rust 中为泛型 struct 编写一次特征绑定

tokio async rust 的 yield 是什么意思?

返回 &str 但不是 String 时,borrow 时间比预期长