2016-07-10 51 views
3

我在Rust Rust中有一個固定大小的數組,我想將它變成(String, String)。我可以在不復制值的情況下執行此操作嗎將數組移動到元組

的一塊,我在特別工作代碼如下:

let (basis, names_0, names_1) = if let Some(names) = self.arg_name { 
    (ComparisonBasis::Name, names[0], names[1]) 
} else { 
    (ComparisonBasis::File, self.arg_file[0], self.arg_file[1]) 
}; 

類型:

self.arg_name: Option<[String; 2]> 
self.arg_file: Vec<String> 

現在,我得到錯誤

cannot move out of type `[std::string::String; 2]`, a non-copy fixed-size array [E0508] 

cannot move out of indexed content [E0507] 

if

+0

最後,我想我有點過分熱衷於嘗試優化克隆的調用。這個問題中的一段代碼每次程序運行只調用一次,它只有兩個(可能很小)的字符串。 – Apanatshka

回答

4

您已經省略了相當數量的上下文,所以我在猜測幾個方面。我也更接近的問題,而不是你的片段隱含的模糊問題。

struct NeverSpecified { 
    arg_names: Option<[String; 2]>, 
    arg_file: Vec<String>, 
} 

impl NeverSpecified { 
    fn some_method_i_guess(mut self) -> (String, String) { 
     if let Some(mut names) = self.arg_names { 
      use std::mem::replace; 
      let name_0 = replace(&mut names[0], String::new()); 
      let name_1 = replace(&mut names[1], String::new()); 
      (name_0, name_1) 
     } else { 
      let mut names = self.arg_file.drain(0..2); 
      let name_0 = names.next().expect("expected 2 names, got 0"); 
      let name_1 = names.next().expect("expected 2 names, got 1"); 
      (name_0, name_1) 
     } 
    } 
} 

我使用std::mem::replace切換數組的內容,而離開它處於有效狀態。這是必要的,因爲Rust不會讓你有一個「部分有效」的數組。此路徑中沒有涉及副本或分配。

在另一個路徑中,我們必須手動將元素拉出矢量。再次,您不能通過索引將值從容器中移出(這實際上是整個索引的限制)。相反,我使用Vec::drain將前兩個元素從矢量中剔除,然後從生成的迭代器中提取它們。要清楚:此路徑不涉及任何副本或分配,或者

順便說一句,那些expect方法不應永遠被觸發(因爲drain做邊界檢查),但比抱歉更好的偏執;如果你想用unwrap()來代替它們,那應該沒問題。

+0

這正是我一直在尋找:)對不起,在問題中的模糊性。 – Apanatshka

+0

@Apanatshka:要清楚,示例中的任何分支都不涉及複製或分配;它*純粹*移動(並在第一個分支中爲空值)。只是想澄清,因爲你對你的問題的評論可能暗示你認爲沒有複製就沒有辦法做到這一點。 –

+0

我明白,你的例子不會做任何複製(但它確實分配新(空)'字符串的權利?)。我只是決定,在這種情況下,調用'clone'是好的,而且稍微不費力地編寫和讀取:) – Apanatshka