2016-11-23 133 views
3

我想回到一個向量的元素:如何從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

@MatthieuM。好的,但我該如何按價值返回元素?我可以克隆/複製它嗎? – plailopo

+0

@Shepmaster我已經嘗試過,但沒有工作 'pub fn findOne(&self) - > Option {self.findAll()。first()。cloned()}' 找不到名爲'clone的'方法 – plailopo

回答

7

看那簽名Vec::first

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

給一個向量的引用,將返回引用的第一個項目,如果有一個,和None否則。這意味着包含值的向量必須超過返回值,否則引用將指向未定義的內存。

主要有兩種途徑:

  1. 如果你不能改變的載體,那麼你需要讓你的數據結構的副本。最簡單的方法是用#[derive(Clone)]註釋結構。然後您可以撥打Option::clonedfirst的結果。

  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. 方式和變量名稱的鏽風格是snake_case
  3. 使用vec!在提供所有元素時構造向量。
  4. 導出Debug因此您可以打印該值。

如果你想始終獲得最後元素,你可以使用pop

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