我可以轉換Vec<String>
到Vec<&str>
這樣:轉換VEC <String>到VEC <&str>
let mut items = Vec::<&str>::new();
for item in &another_items {
items.push(item);
}
我想有更好的方法?
我可以轉換Vec<String>
到Vec<&str>
這樣:轉換VEC <String>到VEC <&str>
let mut items = Vec::<&str>::new();
for item in &another_items {
items.push(item);
}
我想有更好的方法?
這一次使用collect
:
let strs: Vec<&str> = another_items.iter().map(|s| s as &str).collect();
another_items.iter().map(|item| item.deref()).collect::<Vec<&str>>()
要使用deref()
必須添加使用use std::ops::Deref
有不少方法可以做到這一點,一些有缺點,別人根本是更具可讀性對一些人。
此解引用s
(這是&String
類型)到String
「右側的參考」,然後將其通過Deref
性狀給str
「右手側基準」解除引用,然後變回&str
。這是在編譯器中很常見的東西,因此我認爲它是慣用的。
let v2: Vec<&str> = v.iter().map(|s| &**s).collect();
這裏Deref
性狀的deref
功能傳遞給map
功能。它非常整潔,但需要use
特性或完整的路徑。
let v3: Vec<&str> = v.iter().map(std::ops::Deref::deref).collect();
這已被棄用,你不應該這樣做,因爲它可以在未來與|s| s: &str
(強制語法)來完成。
let v4: Vec<&str> = v.iter().map(|s| s as &str).collect();
這需要RangeFull
切片String
的(只是一個切片到整個String
)和需要對它的引用。我認爲這很醜陋。
let v5: Vec<&str> = v.iter().map(|s| &s[..]).collect();
這是使用強制轉換到&String
轉換成&str
。將來也可以用s: &str
表達式替換。
let v6: Vec<&str> = v.iter().map(|s| { let s: &str = s; s }).collect();
以下(感謝@休恩-dbaupp)使用AsRef
性狀,其單獨存在於從所擁有的類型到它們各自的借類型映射。有兩種方法可以使用它,而且任何一個版本的漂亮都完全是主觀的。
let v7: Vec<&str> = v.iter().map(|s| s.as_ref()).collect();
和
let v8: Vec<&str> = v.iter().map(AsRef::as_ref).collect();
我的底線是使用v8
解決方案,因爲它最明確地表達你想要什麼。
其他答案只是工作。我只是想指出的是,如果你想給Vec<String>
轉換成Vec<&str>
只將它傳遞給服用Vec<&str>
作爲自變量的函數,考慮修改函數簽名爲:
fn my_func<T: AsRef<str>>(list: &[T]) { ... }
代替:
fn my_func(list: &Vec<&str>) { ... }
正如這個問題所指出的:Function taking both owned and non-owned string collections。通過這種方式,這兩種載體只需簡單地工作而不需要轉換。
這裏是另一種選擇:
use std::iter::FromIterator;
let v = Vec::from_iter(v.iter().map(String::as_str));
注意String::as_str
是穩定的,因爲鏽病1.7。
顯式調用'deref'(特別是作爲一個自由函數)會讀取很奇怪的IMO,我個人覺得'v2'或'v5'更好。 (也可以使用'as_ref','v.iter()。map(| s | s.as_ref())...'這種形式的泛型轉換的典型方法,例如'std'中的許多函數採取'P:AsRef'。) –
huon
謝謝,你是完全正確的。 「AsRef」在這裏更合適。我更新了這篇文章 –