我可以这样将 Vec<String>
转换为 Vec<&str>
:
let another_items = vec!["foo".to_string(), "bar".to_string()];
let mut items = Vec::<&str>::new();
for item in &another_items {
items.push(item);
}
有没有更好的选择?
我可以这样将 Vec<String>
转换为 Vec<&str>
:
let another_items = vec!["foo".to_string(), "bar".to_string()];
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
函数。这相当不错,但需要使用该特质或提供完整路径。
let v3: Vec<&str> = v.iter().map(std::ops::Deref::deref).collect();
这使用强制类型转换语法。
let v4: Vec<&str> = v.iter().map(|s| s as &str).collect();
这将对String
进行RangeFull
切片(仅切片到整个String
),并对其引用。在我看来,这很丑陋。
let v5: Vec<&str> = v.iter().map(|s| &s[..]).collect();
这里使用强制类型转换将&String
转换成&str
。未来也可以用s: &str
表达式替代。
let v6: Vec<&str> = v.iter().map(|s| { let s: &str = s; s }).collect();
以下内容(感谢@huon-dbaupp)使用了AsRef
trait,它的唯一存在就是将拥有所有权的类型映射到它们各自的借用类型上。有两种使用方法,而且两个版本的美观程度都是完全主观的。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>) { ... }
ExactSizeIterator
,因此它确切地知道它将返回多少元素。map
保留了这一点,collect
通过一次性为ExactSizeIterator
分配足够的空间来利用这个特性。vec.reserve_exact(iter.len())
使得向量拥有准确的内存占用。let mut items = Vec::<&str>::with_capacity(another_items.len());
for item in &another_items {
items.push(item);
}
Vec<String>
转换为Vec<&str>
?” - Shepmasteranother_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
方法已经稳定可用。FromIterator
自2021版起已经在预导入中,因此现在无需导入它。但我认为你不应该在这里使用from_iter()
;collect()
更好。 - Chayim Friedman
deref
(特别是作为自由函数)在我看来读起来相当奇怪,我个人认为v2
或v5
更好。 (也可以使用as_ref
,v.iter().map(| s | s.as_ref())...
这是此类通用转换的典型方法,例如,std
中的许多函数都采用P:AsRef <Path>
。) - huonAsRef
更加合适。我已经更新了帖子。 - oli_obkString::as_str
,这会让你的代码意图更加清晰。 - JeanMertzs as &str
对我来说最有意义,按照惯用方式去理解和记忆在我看来很困难。 - Piotr Zakrzewskicollect
会分配一个新的向量。 - rsalmei