我发现了这种方式,但这种共同行动似乎过于冗长:
fn double_vec(vec: Vec<i32>) -> Vec<i32> {
let mut vec1 = vec.clone();
let vec2 = vec.clone();
vec1.extend(vec2);
vec1
}
我知道在JavaScript中它可能只是arr2 = [...arr1, ...arr1]
。
答案 0 :(得分:5)
你可以使用concat方法,这很简单:
fn double_vec(v: Vec<i32>) -> Vec<i32> {
[&v[..], &v[..]].concat()
}
不幸的是我们必须明确地制作矢量切片(这里是&v[..]
);但是否则这种方法很好,因为它直接将结果分配给所需的大小,然后进行复制。
答案 1 :(得分:4)
“加倍向量”不是经常做的事情,所以没有它的捷径。此外,重要的是Vec
内部的内容,因为它会更改可以对其执行的操作。在此特定示例中,以下代码有效:
let x = vec![1, 2, 3];
let y: Vec<_> = x.iter().cycle().take(x.len() * 2).collect();
println!("{:?}", y); //[1, 2, 3, 1, 2, 3]
cycle()
方法要求Iterator
中的项目实现Clone
特征,以便可以复制项目。因此,如果Vec
中的项目实施Clone
,那么这将有效。由于不可变引用(&
)实现Clone
,Vec<&Something>
将起作用,但可变引用(&mut
)不实现Clone
,因此Vec<&mut Something>
不会起作用。
请注意,即使某个类型未实现Clone
,您仍可以克隆对该类型的引用:
struct Test;
fn test_if_clone<T: Clone>(_x: T) {}
fn main() {
let x = Test;
test_if_clone(x); //error[E0277]: the trait bound `Test: std::clone::Clone` is not satisfied
let y = &x;
test_if_clone(y); //ok
}
答案 2 :(得分:4)
在Wesley的答案的基础上,您还可以使用chain将两个迭代项一个接一个地粘合在一起。在下面的示例中,我使用相同的Vec
iter()
方法两次:
let x = vec![1, 2, 3];
let y: Vec<_> = x.iter().chain(x.iter()).collect();
println!("{:?}", y); //[1, 2, 3, 1, 2, 3]
答案 3 :(得分:3)
迭代器方法可能比向量扩展的直接memcpy
效率低得多。
你自己的代码会clone
太多;你可以重用按值输入:
fn double_vec(mut vec: Vec<i32>) -> Vec<i32> {
let clone = vec.clone();
vec.extend(clone);
vec
}
但是,Vec
的性质意味着即使您设法删除该克隆,也可能需要副本,因此您通常不会仅使用concat
获得更多。
在切片上使用concat
非常有效,因为它会预先预先分配Vec
,然后执行高效的extend_from_slice
。但是,这确实意味着以Vec
作为输入不再特别明智;写下面的内容更加灵活。
fn double_slice(slice: &[i32]) -> Vec<i32> {
[slice, slice].concat()
}