首页 > 解决方案 > 对迭代器进行分区时,Vec 没有实现特征 Extend

问题描述

.partition()调用向量迭代器时遇到错误:

error[E0277]: the trait bound `std::vec::Vec<std::result::Result<std::collections::HashSet<&std::string::String>, std::boxed::Box<dyn std::error::Error>>>: std::iter::Extend<&std::result::Result<std::collections::HashSet<std::string::String>, std::boxed::Box<dyn std::error::Error>>>` is not satisfied
 --> src/main.rs:9:24
  |
9 |         results.iter().partition(|r| r.is_ok());
  |                        ^^^^^^^^^ the trait `std::iter::Extend<&std::result::Result<std::collections::HashSet<std::string::String>, std::boxed::Box<dyn std::error::Error>>>` is not implemented for `std::vec::Vec<std::result::Result<std::collections::HashSet<&std::string::String>, std::boxed::Box<dyn std::error::Error>>>`
  |
  = help: the following implementations were found:
            <std::vec::Vec<T> as std::iter::Extend<&'a T>>
            <std::vec::Vec<T> as std::iter::Extend<T>>

运行以下代码时:

use std::collections::HashSet;

type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;

fn main() {
    let mut results: Vec<Result<HashSet<String>>> = Default::default();

    let (okays, errors): (Vec<Result<HashSet<&String>>>, Vec<_>) =
        results.iter().partition(|r| r.is_ok());
}

以游乐场为例。

标签: rust

解决方案


正如错误消息所述(删除了命名空间):

该特征Extend<&Result<HashSet<String>, Box<dyn Error>>>未实现Vec<Result<HashSet<&String>, Box<dyn Error>>>

您不能使用 type 的Vec<T>元素扩展 a ,&T因为它们不是相同的 type

相反,您可以执行以下操作之一:

  1. 将目标集合的类型更改为Vec<&Result<HashSet<String>>>(或者Vec<_>就像您的第二个目标类型一样,以允许编译器推断内部类型)。

  2. 将引用转换为拥有的值,可能是通过cloneto_owned

  3. 不要迭代引用以开始,使用into_iterdrain代替。

但是,您当前的类型将很难实现或实现起来很昂贵,因为您声明您想要一个拥有Result拥有HashMap引用String.

我认为最好的方法是使用Itertools::partition_mapand into_iter

use itertools::Itertools; // 0.9.0
use std::collections::HashSet;

type Error = Box<dyn std::error::Error>;
type Result<T, E = Error> = std::result::Result<T, E>;

fn main() {
    let mut results: Vec<Result<HashSet<String>>> = Default::default();

    let (errors, okays): (Vec<_>, Vec<_>) = results.into_iter().partition_map(Into::into);
    // let (errors, okays): (Vec<Error>, Vec<HashSet<String>>)
}

也可以看看:


推荐阅读