如何从Rust函数返回向量元素?

pla*_*opo 8 reference vector rust

我想返回一个向量的元素:

struct EntryOne {
    pub name: String,
    pub value: Option<String>,
}

struct TestVec {}

impl TestVec {
    pub fn new() -> TestVec {
        TestVec {}
    }

    pub fn findAll(&self) -> Vec<EntryOne> {
        let mut ret = Vec::new();
        ret.push(EntryOne {
            name: "foo".to_string(),
            value: Some("FooVal".to_string()),
        });
        ret.push(EntryOne {
            name: "foo2".to_string(),
            value: Some("FooVal2".to_string()),
        });
        ret.push(EntryOne {
            name: "foo3".to_string(),
            value: None,
        });
        ret.push(EntryOne {
            name: "foo4".to_string(),
            value: Some("FooVal4".to_string()),
        });

        ret
    }

    pub fn findOne(&self) -> Option<EntryOne> {
        let mut list = &self.findAll();

        if list.len() > 0 {
            println!("{} elements found", list.len());
            list.first()
        } else {
            None
        }
    }
}

fn main() {
    let test = TestVec::new();
    test.findAll();
    test.findOne();
}
Run Code Online (Sandbox Code Playgroud)

(游乐场)

我总是得到这个错误:

error[E0308]: mismatched types
  --> src/main.rs:40:13
   |
35 |     pub fn findOne(&self) -> Option<EntryOne> {
   |                              ---------------- expected `std::option::Option<EntryOne>` because of return type
...
40 |             list.first()
   |             ^^^^^^^^^^^^ expected struct `EntryOne`, found &EntryOne
   |
   = note: expected type `std::option::Option<EntryOne>`
              found type `std::option::Option<&EntryOne>`
Run Code Online (Sandbox Code Playgroud)

如何返回元素?

She*_*ter 10

看看签名Vec::first:

fn first(&self) -> Option<&T>
Run Code Online (Sandbox Code Playgroud)

给定对向量的引用,如果有向量,它将返回对第一个项的引用,None否则返回.这意味着包含值的向量必须比返回值更长,否则引用将指向未定义的内存.

主要有两种途径:

  1. 如果无法更改向量,则需要复制数据结构.最简单的方法是使用注释结构#[derive(Clone)].然后你可以调用Option::cloned结果first.

  2. 如果您可以更改向量,则可以从中删除第一个值并将其返回.有很多方法可以做到这一点,但最短的代码是使用drain迭代器.

#[derive(Debug, Clone)]
struct EntryOne {
    name: String,
    value: Option<String>,
}

fn find_all() -> Vec<EntryOne> {
    vec![
        EntryOne {
            name: "foo".to_string(),
            value: Some("FooVal".to_string()),
        },
        EntryOne {
            name: "foo2".to_string(),
            value: Some("FooVal2".to_string()),
        },
        EntryOne {
            name: "foo3".to_string(),
            value: None,
        },
        EntryOne {
            name: "foo4".to_string(),
            value: Some("FooVal4".to_string()),
        },
    ]
}

fn find_one_by_clone() -> Option<EntryOne> {
    find_all().first().cloned()
}

fn find_one_by_drain() -> Option<EntryOne> {
    let mut all = find_all();
    let mut i = all.drain(0..1);
    i.next()
}

fn main() {
    println!("{:?}", find_one_by_clone());
    println!("{:?}", find_one_by_drain());
}
Run Code Online (Sandbox Code Playgroud)

其他变化:

  1. TestVec如果没有国家就没有必要; 只是做功能.
  2. Rust样式snake_case用于方法和变量名称.
  3. 用于vec!在提供所有元素时构造向量.
  4. 导出,Debug以便您可以打印该值.

如果你想总是得到最后一个元素,你可以使用pop:

fn find_one_by_pop() -> Option<EntryOne> {
    find_all().pop()
}
Run Code Online (Sandbox Code Playgroud)