Ответ 1
Существует несколько способов сделать это, некоторые из них имеют недостатки, другие просто более читабельны для некоторых людей.
Это разделение 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();
Это использует принуждения для преобразования a &String
в &str
. Также может быть заменен выражением s: &str
в будущем.
let v6: Vec<&str> = v.iter().map(|s| { let s: &str = s; s }).collect();
В следующем (спасибо @huon-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
, так как оно явно выражает то, что вы хотите.