在Rust中向量中重复元素的最佳方法是什么?

时间:2017-12-01 20:34:55

标签: vector rust

我发现了这种方式,但这种共同行动似乎过于冗长:

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]

4 个答案:

答案 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,那么这将有效。由于不可变引用(&)实现CloneVec<&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()
}