在Rust中连接向量的最佳方法是什么?

relj7zay  于 2023-01-02  发布在  其他
关注(0)|答案(6)|浏览(131)

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

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

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

有人知道更好的办法吗?

rkue9o1l

rkue9o1l1#

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

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

other的所有元素移动到Self中,other保留为空。
在您的示例中,以下代码将通过mutatingab来连接两个向量:

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]);
xe55xuns

xe55xuns2#

我不能在一条线上完成。
可以使用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

有无数种方法。

ifmq2ha2

ifmq2ha23#

在性能方面,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)
fkaflof6

fkaflof64#

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

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

xxb16uws5#

对Mattia Samiolo的answer进行了一些修复:

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

gtlvzcf86#

一种选择是使用extend方法,它允许你将一个向量的元素附加到另一个向量上,如下所示:

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

a.extend(b);

这将把B的元素附加到a的末尾,得到具有元素[1,2,3,4,5,6]的向量a。
另一种方法是使用std::iter模块中的concat函数来连接两个向量,这个函数将两个向量作为参数,并返回一个新向量,这个新向量是两个输入向量的连接,如下所示:

use std::iter;

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

let c = iter::concat(a, b);

这将创建具有元素[1,2,3,4,5,6]的新向量c。
您也可以使用[..]运算符连接两个向量。此运算符允许您创建一个新向量,该向量是两个输入向量的连接。如下所示:

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

 let c = [&a[..], &b[..]].concat();

这将创建具有元素[1,2,3,4,5,6]的新向量c。

相关问题