web-dev-qa-db-fra.com

Comment convertir un Vec <String> en Vec <& str>?

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?

37
Kalita Alexey

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 useing 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.

36
oli_obk

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.

12
mbrt
another_items.iter().map(|item| item.deref()).collect::<Vec<&str>>()

Pour utiliser deref() vous devez ajouter en utilisant use std::ops::Deref

2
Kalita Alexey

Celui-ci utilise collect:

let strs: Vec<&str> = another_items.iter().map(|s| s as &str).collect();
1
aochagavia

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.

1
malbarbo