ps4 - rust traduccion
Convertir Vec<String> a Vec<& str> (5)
Éste usa collect
:
let strs: Vec<&str> = another_items.iter().map(|s| s as &str).collect();
Puedo convertir Vec<String>
a Vec<&str>
esta manera:
let mut items = Vec::<&str>::new();
for item in &another_items {
items.push(item);
}
Me imagino que hay mejores alternativas?
Aquí hay otra opción:
use std::iter::FromIterator;
let v = Vec::from_iter(v.iter().map(String::as_str));
Tenga en cuenta que String::as_str
es estable desde Rust 1.7.
Hay bastantes formas de hacerlo, algunas tienen desventajas, otras simplemente son más legibles para algunas personas.
Estas referencias no son válidas (que son de tipo &String
) a una "referencia del lado derecho" de la String
, que luego se elimina en referencia a través del rasgo Deref
a una "referencia del lado derecho" y luego se vuelve a convertir en un &str
. Esto es algo que se ve muy comúnmente en el compilador, y por eso lo considero idiomático.
let v2: Vec<&str> = v.iter().map(|s| &**s).collect();
Aquí la función Deref
rasgo Deref
se pasa a la función de map
. Es bastante bueno, pero requiere el use
del rasgo o la ruta completa.
let v3: Vec<&str> = v.iter().map(std::ops::Deref::deref).collect();
Esto está en desuso, no debe hacer esto, ya que puede hacerse en el futuro con |s| s: &str
|s| s: &str
(sintaxis de coerción).
let v4: Vec<&str> = v.iter().map(|s| s as &str).collect();
Esto toma una RangeFull
de la String
(solo una porción en toda la String
) y toma una referencia a ella. Es feo en mi opinión.
let v5: Vec<&str> = v.iter().map(|s| &s[..]).collect();
Este es el uso de coerciones para convertir un &String
en un &str
. También puede ser reemplazado por una expresión s: &str
en el futuro.
let v6: Vec<&str> = v.iter().map(|s| { let s: &str = s; s }).collect();
Lo siguiente (gracias @ huon-dbaupp) usa el rasgo AsRef
, que solo existe para mapear desde los tipos AsRef
a sus respectivos tipos prestados. Hay dos formas de usarlo y, una vez más, la belleza de cualquiera de las versiones es completamente subjetiva.
let v7: Vec<&str> = v.iter().map(|s| s.as_ref()).collect();
y
let v8: Vec<&str> = v.iter().map(AsRef::as_ref).collect();
Mi conclusión es usar la solución v8
, ya que expresa de manera más explícita lo que desea.
Las otras respuestas simplemente funcionan. Solo quiero señalar que si está intentando convertir el Vec<String>
en un Vec<&str>
solo para pasarlo a una función que tome el Vec<&str>
como argumento, considere revisar la firma de la función como:
fn my_func<T: AsRef<str>>(list: &[T]) { ... }
en lugar de:
fn my_func(list: &Vec<&str>) { ... }
Como lo señala esta pregunta: Función que toma colecciones de cadenas tanto propias como no propias . De esta manera, ambos vectores simplemente funcionan sin la necesidad de conversiones.
another_items.iter().map(|item| item.deref()).collect::<Vec<&str>>()
Para usar deref()
debe agregar usar use std::ops::Deref