如何划分可变借入的向量?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何划分可变借入的向量?相关的知识,希望对你有一定的参考价值。

如果我有一个本地的,可变的向量,我可以按如下方式对其进行分区,从partition的文档中复制。

let mut a = vec![1, 2, 3, 4];
let (even, odd): (Vec<i32>, Vec<i32>) = a.into_iter().partition(|&n| n % 2 == 0);

在此过程中消耗(移动)a向量。但是,如果我有一个借用的可变引用,则对分区的相同调用不起作用。如果我在这种情况下尝试使用相同的代码,我会收到错误:

error[E0277]: the trait bound `std::vec::Vec<i32>: std::iter::Extend<&mut i32>` is not satisfied
 --> src/main.rs:2:59
  |
2 |     let (even, odd): (Vec<i32>, Vec<i32>) = a.into_iter().partition(|n| **n % 2 == 0);
  |                                                           ^^^^^^^^^ the trait `std::iter::Extend<&mut i32>` is not implemented for `std::vec::Vec<i32>`
  |
  = 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>>

基于How to make a Rust mutable reference immutable?,我写了以下内容,它编译并将正确的值放入evenodd

fn doit(a: &mut Vec<i32>) {
    let (even, odd): (Vec<i32>, Vec<i32>) = (&*a).into_iter().partition(|&n| n % 2 == 0);
    println!("even {:?}, odd {:?}, a {:?}", even, odd, a);
}

但是,即使我使用into_iter(),这也不会消耗原始矢量。有一些关于可变性,借用或迭代器的东西,我只是没有到达这里。

答案

正如其他人暗示的那样,您不能移动原始矢量,因为您不拥有它。但是,您可以将所有值移出矢量,将其留空。这可以使用drain方法完成:

fn doit(a: &mut Vec<i32>) {
    let (even, odd): (Vec<i32>, Vec<i32>) = a.drain(..).partition(|&n| n % 2 == 0);
    println!("even {:?}, odd {:?}, a {:?}", even, odd, a);
}

playground

另一答案

原因是对于&'a mut Vec<T>&'a Vec<T>,IntoIterator特性的实现方式不同,那么它适用于Vec<T>。前两个按值创建迭代器,其中Vec<T>版本创建一个消费迭代器,即将每个值移出向量(从开始到结束)的迭代器。调用into_iter()后无法使用该向量。因此,您可以将前两个&'a mut Vec<T>&'a Vec<T>视为使用Vector中引用的值来创建迭代器。在Vec<T>,你可以想到它从Vec<T>中删除值并将它们放入迭代器。 Shepmaster关于不能消费你不拥有的东西的评论是他们以不同方式实施的原因。

还要注意,有不同的方法来获取迭代器。来自Rust文档:

  • iter(),迭代&T
  • iter_mut(),迭代&mut T
  • into_iter(),迭代T

所以你也可以通过使用(&*a)而不是iter()来保持函数相同而不用into_iter()

fn doit(a: &mut Vec<i32>) {
    let (even, odd): (Vec<i32>, Vec<i32>) = a.iter().partition(|&n| n % 2 == 0);
    println!("even {:?}, odd {:?}, a {:?}", even, odd, a);
}

以上是关于如何划分可变借入的向量?的主要内容,如果未能解决你的问题,请参考以下文章

在几个可变 lambda 中更改相同的向量

如何使用 C++11 可变参数模板来定义由向量元组支持的元组向量?

如何从可变数量的 STL 向量创建变量的所有排列 [重复]

引用向量的部分片段?

如何在Rust中修改向量的元素?

2021-12-24:划分字母区间。 字符串 S 由小写字母组成。我们要把这个字符串划分为尽可能多的片段,同一字母最多出现在一个片段中。返回一个表示每个字符串片段的长度的列表。 力扣763。某大厂面试