Je peux convertir Vec<String>
à Vec<&str>
par ici:
let mut items = Vec::<&str>::new();
for item in &another_items {
items.Push(item);
}
Y a-t-il de meilleures alternatives?
Il existe plusieurs façons de le faire, certaines présentent des inconvénients, d'autres sont tout simplement plus lisibles pour certaines personnes.
Cela déréférence s
(qui est de type &String
) à une String
"référence de droite", qui est ensuite déréférencée par le trait Deref
à une str
"référence de droite" puis à nouveau une &str
. C'est quelque chose qui est très communément vu dans le compilateur, et je le considère donc idiomatique.
let v2: Vec<&str> = v.iter().map(|s| &**s).collect();
Ici, la fonction deref
du trait Deref
est passée à la fonction map
. C'est assez soigné mais nécessite use
ing le trait ou donnant le chemin complet.
let v3: Vec<&str> = v.iter().map(std::ops::Deref::deref).collect();
Cela utilise la syntaxe de coercition.
let v4: Vec<&str> = v.iter().map(|s| s as &str).collect();
Cela prend une tranche de RangeFull
de la String
(juste une tranche dans la totalité de la String
) et y prend une référence. C'est moche à mon avis.
let v5: Vec<&str> = v.iter().map(|s| &s[..]).collect();
Il s'agit de coercitions pour convertir un &String
dans une &str
. Peut également être remplacé par un s: &str
expression dans le futur.
let v6: Vec<&str> = v.iter().map(|s| { let s: &str = s; s }).collect();
Ce qui suit (merci @ huon-dbaupp) utilise le trait AsRef
, qui existe uniquement pour mapper des types possédés à leur type emprunté respectif. Il y a deux façons de l'utiliser, et encore une fois, la beauté de l'une ou l'autre version est entièrement subjective.
let v7: Vec<&str> = v.iter().map(|s| s.as_ref()).collect();
et
let v8: Vec<&str> = v.iter().map(AsRef::as_ref).collect();
Mon résultat est d'utiliser le v8
solution car elle exprime le plus explicitement ce que vous voulez.
Les autres réponses fonctionnent simplement. Je veux juste souligner que si vous essayez de convertir le Vec<String>
dans une Vec<&str>
uniquement pour le passer à une fonction prenant Vec<&str>
comme argument, envisagez de réviser la signature de la fonction comme:
fn my_func<T: AsRef<str>>(list: &[T]) { ... }
au lieu de:
fn my_func(list: &Vec<&str>) { ... }
Comme indiqué par cette question: Fonction prenant à la fois les collections de chaînes possédées et non possédées . De cette façon, les deux vecteurs fonctionnent simplement sans avoir besoin de conversions.
another_items.iter().map(|item| item.deref()).collect::<Vec<&str>>()
Pour utiliser deref()
vous devez ajouter en utilisant use std::ops::Deref
Celui-ci utilise collect
:
let strs: Vec<&str> = another_items.iter().map(|s| s as &str).collect();
Voici une autre option:
use std::iter::FromIterator;
let v = Vec::from_iter(v.iter().map(String::as_str));
Notez que String::as_str
est stable depuis Rust 1.7.