Я могу преобразовать 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.