如何在一行中连接不可变向量?

Ste*_*ein 4 vector concatenation rust

我有不可变的向量ab其中元素的复制成本很低,我想创建一个向量来形成这些现有向量的串联而不改变它们 (*)。

如果其中一个向量是可变的则较早的问题解决了这个问题,因此一个明显的答案是首先克隆向量a,例如

let mut r = a.clone();
r.extend(&b);
Run Code Online (Sandbox Code Playgroud)

但这似乎既不优雅也不高效(扩展很容易导致不必要的重新分配,对吧?)。我(作为 Rust 菜鸟)提出(修正后的)最佳选择是:

fn cat(a: &Vec<i32>, b: &Vec<i32>) -> Vec<i32> {
    let mut r = Vec::<i32>::with_capacity(a.len() + b.len());
    r.extend(a);
    r.extend(b);
    r
}
Run Code Online (Sandbox Code Playgroud)

由于元素复制起来很便宜,因此对于字符串向量更通用问题的答案应该适用于这里,但vec![a, b].concat()只有当您通过将向量移动到向量中来构造向量向量时,这似乎才有效,因为会vec![&a, &b].concat()产生“未concat找到命名的方法”。

对于这项看似简单的工作,即使它不是最佳的,是否有一种单行方式?


(*) 原来“不改变”有两种含义:

  • 只是不可变的,这在 Rust 中意味着如果代码编译,它不会看到具有更改值的变量;但变量可能会被移出,进一步或未来的代码不能再使用它
  • 实际上是只读的,保留变量不变以供进一步或将来的代码使用

hel*_*low 5

concat 确实有效,如果使用得当:

fn cat(a: &[i32], b: &[i32]) -> Vec<i32> {
    [a, b].concat()
}

fn main() {
    let a = vec![1, 2, 3];
    let b = vec![7, 8, 9];
    println!("{:?}", cat(&a, &b));
}
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,我现在明白了。实际的单行代码是“[a.as_slice(), b.as_slice()].concat()”,并且函数调用隐式地执行了切片操作。 (2认同)

car*_*ver 5

数组可以concat()切片为向量,你只需要给编译器一个更强的提示:

let combined = [a.as_slice(), b.as_slice()].concat();
Run Code Online (Sandbox Code Playgroud)

这里有一个Rust 游乐场,可以尝试一下。可以看到 和 都没有ab消耗,并且combined是一个新的向量。&请注意,如果您尝试使用借用的简写而不是指定 ,则会失败as_slice()