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

6

我想要做什么:

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]
}

我理解当我调用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);
2个回答

8
尝试弄清楚为什么借用检查器会抱怨时,识别涉及的类型可能会很有用。
如果您打出以下内容:
let _: () = test_vec.last().map(|v| v.clone());

您会收到一个错误,指出()core::option::Option<&Test>不是相同的类型。
发生了什么?简单地说,如果您克隆一个&Test,则会得到一个&Test,因此在Option<&Test>上调用.map(|v| v.clone())会给出一个Option<&Test>。显然,它仍然借用。
您下一次尝试时遇到了同样的问题,如果您键入:
let _: () = test_vec.last().unwrap().clone();

你会收到一个错误,提示()&Test不是相同的类型。
Option<&Test>上调用unwrap将得到一个&Test,然后将其克隆为一个&Test
所以,问题在于缺少解引用。你需要更早地进行解引用,以避免在Some(last)中借用test_vec
if let Some(last) = test_vec.last().map(|v| (*v).clone()) {
    test_vec.push(last);
}

当然,这并不起作用,因为 Test 没有实现 clone。 一旦修复了这个问题(通过 #[derive(Clone)]),它就可以编译。
由于从引用进行克隆是一个如此常见的需求,Option(和Iterator)有一个专门的方法叫做 cloned:
if let Some(last) = test_vec.last().cloned() {
    test_vec.push(last);
}

7
为解决借用问题,您可以调用Option::cloned,该方法将从Option<&T>生成一个Option<T>。为此,Test必须实现Clone。您可以使用derive实现TestClone
// 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);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接