我有不可变的向量a
和b
,其中的元素很容易复制,我想创建一个向量来构成这些现有向量的级联,而不更改它们(*)。
An earlier question addressed it if one of the vectors is mutable,所以一个明显的答案是首先克隆载体a
,例如
let mut r = a.clone();
r.extend(&b);
但这似乎既不优雅也不高效(扩展很容易导致不必要的重新分配,对吧?)。 (corrected) best alternative I (being a Rust noob) come up with是:
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
}
由于元素的复制成本很低,因此more generic question for vectors of strings的答案应在此处应用,但是vec![a, b].concat()
似乎只有在通过将向量移入向量来构造向量的情况下才有效,因为{{ 1}}产生“找不到名为vec![&a, &b].concat()
的方法”。
即使不是最佳选择,对于看似简单的工作是否也只有一线?
(*)证明“不更改”有两种含义:
答案 0 :(得分:2)
编者注:提供此答案后,OP改变了他们的问题。请参考创建此答案的version of the question。
您的第一个示例实际上没有任何意义。您提到了不变性,但是由于您将向量的所有权转移给cat
函数,因此它可以选择变量的可变性。在这种情况下,您最好重用其中之一的分配:
fn cat(mut a: Vec<i32>, b: Vec<i32>) -> Vec<i32> {
a.extend(b);
a
}
扩展很容易导致不必要的重新分配
从技术上讲这是可行的,但极不可能。迭代器使用方法size_hint
是有原因的-允许集合尽可能精确地分配。
单线
a.into_iter().chain(b).collect::<Vec<_>>()
这会破坏向量a
和b
(而不是其中的元素)的分配,并创建一个新的分配来容纳所有项目。
如果您的切片不可变,则可以使用相同的技术:
fn cat<T: Clone>(a: &[T], b: &[T]) -> Vec<T> {
a.iter().chain(b).cloned().collect()
}
另请参阅:
答案 1 :(得分:2)
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));
}