Я могу преобразовать Vec<String> в Vec<&str> следующим образом:
let mut items = Vec::<&str>::new();
for item in &another_items {
items.push(item);
}
Я предполагаю, что есть лучшие альтернативы?
Я могу преобразовать Vec<String> в Vec<&str> следующим образом:
let mut items = Vec::<&str>::new();
for item in &another_items {
items.push(item);
}
Я предполагаю, что есть лучшие альтернативы?
Существует несколько способов сделать это, некоторые из них имеют недостатки, другие просто более читабельны для некоторых людей.
Это разделение 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, так как оно явно выражает то, что вы хотите.
Другие ответы просто работают. Я просто хочу указать, что если вы пытаетесь преобразовать Vec<String> в Vec<&str> только для передачи его функции, принимающей Vec<&str> в качестве аргумента, рассмотрите пересмотр сигнатуры функции как:
fn my_func<T: AsRef<str>>(list: &[T]) { ... }
вместо:
fn my_func(list: &Vec<&str>) { ... }
Как отметил этот вопрос: Функция, взявшая как принадлежащие, так и не принадлежащие коллекции строк. Таким образом, оба вектора просто работают без необходимости преобразований.
another_items.iter().map(|item| item.deref()).collect::<Vec<&str>>()
Чтобы использовать deref(), вы должны добавить с помощью use std::ops::Deref
Этот использует collect:
let strs: Vec<&str> = another_items.iter().map(|s| s as &str).collect();
Вот еще один вариант:
use std::iter::FromIterator;
let v = Vec::from_iter(v.iter().map(String::as_str));
Обратите внимание, что String::as_str является стабильным с Rust 1.7.