获取向量的最后一个元素并将其推送到同一向量

Bra*_*ram 4 vector rust

我想做什么:

enum Test {
    Value1,
    Value2,
    Value3
}

fn main() {
    let mut test_vec: Vec<Test> = Vec::new();
    test_vec.push(Test::Value2);

    if let Some(last) = test_vec.last() {
        test_vec.push(*last);
    }
    //Wanted output: vector with [Test::Value2, Test::Value2]
}
Run Code Online (Sandbox Code Playgroud)

我明白,当我打电话时last(),它会返回Option<&Test> 所以它会借用test_vec直到if-let块结束.

我尝试了以下但没有成功:

if let Some(last) = test_vec.last().map(|v| v.clone()) {
    test_vec.push(*last);
}

//and

let last = test_vec.last().unwrap().clone();
test_vec.push(*last);
Run Code Online (Sandbox Code Playgroud)

Mat*_* M. 8

当试图找出借用检查器抱怨的原因时,识别所涉及的类型会很有用。

如果你输入:

let _: () = test_vec.last().map(|v| v.clone());
Run Code Online (Sandbox Code Playgroud)

你得到一个错误,抱怨()core::option::Option<&Test>是不是同一类型。

这是怎么回事?非常简单地说,如果你克隆 an&Test你会得到 an &Test,因此调用.map(|v| v.clone())aOption<&Test>会得到一个Option<&Test>。显然,它仍然在借钱。

如果您输入:

let _: () = test_vec.last().unwrap().clone();
Run Code Online (Sandbox Code Playgroud)

你得到一个错误,抱怨()&Test是不是同一类型。

通过调用unwrapanOption<&Test>你会得到一个&Test然后被克隆到一个&Test.


所以,问题是缺乏解引用。您需要提前取消引用,以避免借贷test_vecSome(last)

if let Some(last) = test_vec.last().map(|v| (*v).clone()) {
    test_vec.push(last);
}
Run Code Online (Sandbox Code Playgroud)

当然,这不起作用,因为Test没有实现clone。一旦修复(通过#[derive(Clone)]),它就会编译。

由于从引用克隆是一种常见的需求,因此在Option(和Iterator)上有一个专用方法,称为cloned

if let Some(last) = test_vec.last().cloned() {
    test_vec.push(last);
}
Run Code Online (Sandbox Code Playgroud)


mal*_*rbo 6

要解决借用问题,你可以调用Option::cloned,从而产生Option<T>a Option<&T>.要做到这一点,Test必须实施Clone.您可以实现CloneTest使用derive:

// To allow assert_eq, we also derive Debug and PartialEq
#[derive(Debug, PartialEq, Clone)]
enum Test {
    Value1,
    Value2,
    Value3
}

fn main() {
    let mut test_vec = Vec::new();
    test_vec.push(Test::Value2);

    if let Some(last) = test_vec.last().cloned() {
        test_vec.push(last);
    }

    assert_eq!(vec![Test::Value2, Test::Value2], test_vec);
}
Run Code Online (Sandbox Code Playgroud)