在Rust中连接向量的最佳方法

Joe*_*mas 37 vector concatenation rust

甚至可以在Rust中连接向量吗?如果是这样,有没有一种优雅的方式呢?我有这样的事情:

let mut a = vec![1, 2, 3];
let b = vec![4, 5, 6];

for val in &b {
    a.push(val);
}
Run Code Online (Sandbox Code Playgroud)

有谁知道更好的方法?

Lud*_*Lud 54

结构std::vec::Vec有方法append():

fn append(&mut self, other: &mut Vec<T>)
Run Code Online (Sandbox Code Playgroud)

移动的所有元素other进入Self,留下other空.

从你的例子,下面的代码将通过连接两个向量变异 ab:

fn main() {
    let mut a = vec![1, 2, 3];
    let mut b = vec![4, 5, 6];

    a.append(&mut b);

    assert_eq!(a, [1, 2, 3, 4, 5, 6]);
    assert_eq!(b, []);
}
Run Code Online (Sandbox Code Playgroud)

或者,您可以使用Extend::extend()将可以转换为迭代器(例如Vec)的所有元素追加到给定的向量:

let mut a = vec![1, 2, 3];
let b = vec![4, 5, 6];

a.extend(b);
assert_eq!(a, [1, 2, 3, 4, 5, 6]);
// b is moved and can't be used anymore
Run Code Online (Sandbox Code Playgroud)

请注意,向量b移动而不是清空.如果向量包含实现的元素,则Copy可以将不可变引用传递给一个向量,extend()以避免移动.在这种情况下,矢量b不会改变:

let mut a = vec![1, 2, 3];
let b = vec![4, 5, 6];

a.extend(&b);
assert_eq!(a, [1, 2, 3, 4, 5, 6]);
assert_eq!(b, [4, 5, 6]);
Run Code Online (Sandbox Code Playgroud)


Sta*_*eur 40

我不能在一行中完成。达米安·齐亚杜克

可以使用chain()以下方法在一行中完成:

let c: Vec<i32> = a.into_iter().chain(b.into_iter()).collect(); // Consumed
let c: Vec<&i32> = a.iter().chain(b.iter()).collect(); // Referenced
let c: Vec<i32> = a.iter().cloned().chain(b.iter().cloned()).collect(); // Cloned
let c: Vec<i32> = a.iter().copied().chain(b.iter().copied()).collect(); // Copied
Run Code Online (Sandbox Code Playgroud)

有无限的方法。

  • @DamianDziaduch 哇,那个***广泛***,你要我解释 Rust ;) 如果你有经验,你可以理解以下内容:基本上消耗移动数据,所以 `a` 和 `b` 是 **not**不再可用,结果可以自由地做它想做的事。引用只是借用这两个向量,所以你需要让他们活着,只要结果想要活着。Clone 和 Copy 非常接近,第一个可能很贵,第二个应该便宜。他们只是将这两个向量用作源,而后者不需要它们,因此结果可以自由地存在,只要它想要,就像 `a` 和 `b`。希望很清楚。 (8认同)
  • 消费、克隆和复制有什么区别?我认为只有参考(借用,是吗?)和克隆 (2认同)

小智 20

我认为连接一个或多个向量的最佳方法是:

let first_number: Vec<usize> = Vec::from([0]);
let final_number: Vec<usize> = Vec::from([3]);
let middle_numbers: Vec<usize> = Vec::from([1,2]);

let numbers = [input_layer, middle_layers, output_layer].concat();
Run Code Online (Sandbox Code Playgroud)


Tia*_*Shi 7

至于性能,slice::concatappendextend大约相同。如果您不需要立即获得结果,将其设为链式迭代器是最快的;如果需要collect(),它是最慢的:

#![feature(test)]

extern crate test;

use test::Bencher;

#[bench]
fn bench_concat___init__(b: &mut Bencher) {
    b.iter(|| {
        let mut x = vec![1i32; 100000];
        let mut y = vec![2i32; 100000];
    });
}

#[bench]
fn bench_concat_append(b: &mut Bencher) {
    b.iter(|| {
        let mut x = vec![1i32; 100000];
        let mut y = vec![2i32; 100000];
        x.append(&mut y)
    });
}

#[bench]
fn bench_concat_extend(b: &mut Bencher) {
    b.iter(|| {
        let mut x = vec![1i32; 100000];
        let mut y = vec![2i32; 100000];
        x.extend(y)
    });
}

#[bench]
fn bench_concat_concat(b: &mut Bencher) {
    b.iter(|| {
        let mut x = vec![1i32; 100000];
        let mut y = vec![2i32; 100000];
        [x, y].concat()
    });
}

#[bench]
fn bench_concat_iter_chain(b: &mut Bencher) {
    b.iter(|| {
        let mut x = vec![1i32; 100000];
        let mut y = vec![2i32; 100000];
        x.into_iter().chain(y.into_iter())
    });
}

#[bench]
fn bench_concat_iter_chain_collect(b: &mut Bencher) {
    b.iter(|| {
        let mut x = vec![1i32; 100000];
        let mut y = vec![2i32; 100000];
        x.into_iter().chain(y.into_iter()).collect::<Vec<i32>>()
    });
}
Run Code Online (Sandbox Code Playgroud)
running 6 tests
test bench_concat___init__           ... bench:      27,261 ns/iter (+/- 3,129)
test bench_concat_append             ... bench:      52,820 ns/iter (+/- 9,243)
test bench_concat_concat             ... bench:      53,566 ns/iter (+/- 5,748)
test bench_concat_extend             ... bench:      53,920 ns/iter (+/- 7,329)
test bench_concat_iter_chain         ... bench:      26,901 ns/iter (+/- 1,306)
test bench_concat_iter_chain_collect ... bench:     190,334 ns/iter (+/- 16,107)
Run Code Online (Sandbox Code Playgroud)

  • 我看到这个链条仍然断了……太悲伤了。你的 bench_concat_iter_chain 什么都不做,迭代器很懒 (4认同)