【问题标题】:How do I return a vector element from a Rust function?如何从 Rust 函数返回向量元素?
【发布时间】:2017-04-07 11:46:32
【问题描述】:

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

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

如何返回元素?

【问题讨论】:

  • 你了解值和对值的引用之间的区别吗?
  • @MatthieuM。好的,但是如何按值返回元素?我可以克隆/复制它吗?
  • @Shepmaster 我已经尝试过了,但不起作用pub fn findOne(&amp;self) -&gt; Option&lt;EntryOne&gt; {self.findAll().first().cloned()} 找不到名为cloned 的方法

标签: vector reference rust


【解决方案1】:

查看Vec::first的签名:

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

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

有两种主要途径:

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

  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());
}

其他更改:

  1. 如果没有状态,则不需要TestVec;只做函数。
  2. Rust 样式是 snake_case 用于方法和变量名称。
  3. 在提供所有元素时使用vec! 构造一个向量。
  4. 派生Debug,以便您可以打印该值。

如果你想总是得到 last 元素,你可以使用pop:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多