我可以转换Vec<String>成Vec<&str>这种方式:
let mut items = Vec::<&str>::new();
for item in &another_items {
items.push(item);
}
Run Code Online (Sandbox Code Playgroud)
我想有更好的选择?
oli*_*obk 32
有很多方法可以做到这一点,有些方法有缺点,有些方法对某些人来说更具可读性.
这种解除引用s(属于类型&String)到String"右侧参考",然后通过Deref特征将其解除引用到str"右侧参考"然后转回到a &str.这是编译器中常见的东西,因此我认为它是惯用的.
let v2: Vec<&str> = v.iter().map(|s| &**s).collect();
Run Code Online (Sandbox Code Playgroud)
这里deref的功能Deref性状传递给map函数.它非常整洁,但需要use特性或提供完整的路径.
let v3: Vec<&str> = v.iter().map(std::ops::Deref::deref).collect();
Run Code Online (Sandbox Code Playgroud)
这是不推荐的,你不应该这样做,因为它可以在将来用|s| s: &str(强制语法)完成.
let v4: Vec<&str> = v.iter().map(|s| s as &str).collect();
Run Code Online (Sandbox Code Playgroud)
这需要一小RangeFull部分String(只是整个切片String)并对其进行引用.在我看来这很难看.
let v5: Vec<&str> = v.iter().map(|s| &s[..]).collect();
Run Code Online (Sandbox Code Playgroud)
This is uses coercions to convert a &String into a &str. Can also be replaced by a s: &str expression in the future.
let v6: Vec<&str> = v.iter().map(|s| { let s: &str = s; s }).collect();
Run Code Online (Sandbox Code Playgroud)
The following (thanks @huon-dbaupp) uses the AsRef trait, which solely exists to map from owned types to their respective borrowed type. There's two ways to use it, and again, prettyness of either version is entirely subjective.
let v7: Vec<&str> = v.iter().map(|s| s.as_ref()).collect();
Run Code Online (Sandbox Code Playgroud)
and
let v8: Vec<&str> = v.iter().map(AsRef::as_ref).collect();
Run Code Online (Sandbox Code Playgroud)
My bottom line is use the v8 solution since it most explicitly expresses what you want.
mbr*_*brt 12
其他答案只是工作.我只是想指出,如果你试图将其Vec<String>转换为Vec<&str>仅将其传递给Vec<&str>作为参数的函数,请考虑将函数签名修改为:
fn my_func<T: AsRef<str>>(list: &[T]) { ... }
Run Code Online (Sandbox Code Playgroud)
代替:
fn my_func(list: &Vec<&str>) { ... }
Run Code Online (Sandbox Code Playgroud)
正如这个问题所指出的:函数采用自有和非拥有的字符串集合.通过这种方式,两个向量都可以在不需要转换的情况下工作.
所有答案都惯用使用迭代器和收集而不是循环,但没有解释为什么这样做更好。
在循环中,首先创建一个空向量,然后将其推入其中。Rust 对其用于增长因子的策略不做任何保证,但我相信当前的策略是,每当超出容量时,向量容量就会加倍。如果原始向量的长度为 20,则将进行 1 次分配和 5 次重新分配。
从向量迭代会产生一个具有“大小提示”的迭代器。在这种情况下,迭代器实现ExactSizeIterator,因此它确切地知道它将返回多少个元素。map保留这一点并collect通过一次性为ExactSizeIterator.
您还可以通过以下方式手动执行此操作:
let mut items = Vec::<&str>::with_capacity(another_items.len());
for item in &another_items {
items.push(item);
}
Run Code Online (Sandbox Code Playgroud)
到目前为止,堆分配和重新分配可能是整个过程中最昂贵的部分;当不涉及新的堆分配时,比获取引用或写入或推送到向量要昂贵得多。如果一次性将 1000 个元素推送到分配给该长度的向量上比推送 5 个元素(在此过程中需要 2 次重新分配和 1 次分配)更快,我不会感到惊讶。
另一个不为人知的优点是,使用方法collect不会存储在可变变量中,如果不需要,则不应使用该变量。
这个使用collect:
let strs: Vec<&str> = another_items.iter().map(|s| s as &str).collect();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7696 次 |
| 最近记录: |