什么是将许多载体连接成新载体的最佳方法?

时间:2016-09-01 05:47:40

标签: vector rust

要创建一个包含其他向量内容的新向量,我现在正在这样做:

fn func(a: &Vec<i32>, b: &Vec<i32>, c: &Vec<i32>) {
    let abc = Vec<i32> = {
        let mut tmp = Vec::with_capacity(a.len(), b.len(), c.len());
        tmp.extend(a);
        tmp.extend(b);
        tmp.extend(c);
        tmp
    };

    // ...
}

有没有更直接/更优雅的方式来做到这一点?

2 个答案:

答案 0 :(得分:4)

可以使用concat方法,但是值必须是切片,或者可以借给切片,而不是问题中给出的&Vec<_>

一个例子,类似于问题:

fn func(a: &Vec<i32>, b: &Vec<i32>, c: &Vec<i32>) {
    let abc = Vec<i32> = [a.as_slice(), b.as_slice(), c.as_slice()].concat();

    // ...
}

但是,正如@mindTree所指出的那样,使用&[i32]类型参数更加惯用,并且无需转换。例如:

fn func(a: &[i32], b: &[i32], c: &[i32]) {
    let abc = Vec<i32> = [a, b, c].concat();

    // ...
}

SliceConcatExt::concat是函数的更通用版本,可以将多个切片连接到Vec。它将每个切片的大小相加以预先分配正确容量的Vec,然后重复扩展。

fn concat(&self) -> Vec<T> {
    let size = self.iter().fold(0, |acc, v| acc + v.borrow().len());
    let mut result = Vec::with_capacity(size);
    for v in self {
        result.extend_from_slice(v.borrow())
    }
    result
}

答案 1 :(得分:2)

One possible solution might be to use the Chain iterator:

let abc: Vec<_> = a.iter().chain(b).chain(c).collect();

However, in your example you are borrowing the slices, so we'll need to either deref each borrowed element or use the Cloned iterator to copy each integer. Cloned is probably a bit easier and as efficient as we are working with small Copy data (i32):

let abc: Vec<_> = a.iter().cloned()
    .chain(b.iter().cloned())
    .chain(c.iter().cloned())
    .collect();

Seeing as each of these iterators are ExactSizeIterators, it should be possible to allocate the exact size for the target Vec up front, however I'm unware whether or not this is actually the case in the std implementation (they might be waiting on specialization to land before adding this optimisation).