简体   繁体   English

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

[英]How do I return a vector element from a Rust function?

I would like to return an element of a vector: 我想返回一个向量的元素:

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 ) 游乐场

I always get this error: 我总是得到这个错误:

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

How do I return an element? 如何返回元素?

Look at the signature for Vec::first : 看看Vec::first的签名:

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

Given a reference to a vector, it will return a reference to the first item if there is one, and None otherwise. 给定对向量的引用,如果有向量,它将返回对第一个项的引用,否则返回None That means that the vector containing the values must outlive the return value, otherwise the reference would point to undefined memory. 这意味着包含值的向量必须比返回值更长,否则引用将指向未定义的内存。

There are two main avenues: 主要有两种途径:

  1. If you cannot change the vector, then you will need to make a copy of your data structure. 如果无法更改向量,则需要复制数据结构。 The easiest way to do this is to annotate the structure with #[derive(Clone)] . 最简单的方法是使用#[derive(Clone)]注释结构。 Then you can call Option::cloned on the result of first . 然后,你可以调用Option::cloned上的结果first

  2. If you can change the vector, then you can remove the first value from it and return it. 如果您可以更改向量,则可以从中删除第一个值并将其返回。 There are many ways of doing this, but the shortest code-wise is to use the drain iterator. 有很多方法可以做到这一点,但最短的代码是使用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());
}

Additional changes: 其他变化:

  1. There's no need for TestVec if there's no state; 如果没有状态,就不需要TestVec ; just make functions. 只是做功能。
  2. Rust style is snake_case for method and variable names. Rust样式是方法和变量名称的snake_case
  3. Use vec! 使用vec! to construct a vector when providing all the elements. 在提供所有元素时构造向量。
  4. Derive Debug so you can print the value. 导出Debug以便您可以打印该值。

If you wanted to always get the last element, you can use pop : 如果你想总是得到最后一个元素,你可以使用pop

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM