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

时间:2016-11-23 12:44:19

标签: vector reference 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();
}

playground

我总是收到这个错误:

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>`

如何返回元素?

1 个答案:

答案 0 :(得分:10)

查看Vec::first的签名:

fn first(&self) -> Option<&T>

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

主要有两种途径:

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

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

  4. #[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());
    }
    

    其他更改:

    1. 如果没有州,则TestVec不需要;只是做功能。
    2. 方法和变量名称的Rust样式为snake_case
    3. 在提供所有元素时使用vec!构建向量。
    4. 导出Debug,以便您可以打印该值。
    5. 如果您想要始终获取 last 元素,可以使用pop

      fn find_one_by_pop() -> Option<EntryOne> {
          find_all().pop()
      }