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

有可能在 Rust 中连接向量吗?如果是这样,有没有一种优雅的方式来做到这一点?我有这样的东西:

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


for val in &b {
a.push(val);
}

有人知道更好的办法吗?

135134 次浏览

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

fn append(&mut self, other: &mut Vec<T>)

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, []);
}

或者,您可以使用 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

请注意,向量 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]);

我不能排成一列,Damian Dziaduch

通过使用 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

有无数种方法。

在性能方面,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>>()
});
}
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)

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

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();

对 Mattia Samiolo 的 回答做了一些修改:

            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 = [first_number, middle_numbers, final_number].concat();
println!("{:?}", numbers);