Лучший способ конкатенации векторов в Rust

Можно ли даже конкатенировать векторы в Rust? Если это так, есть ли элегантный способ сделать это? У меня есть что-то вроде этого:

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

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

Кто-нибудь знает лучший способ?

Ответ 1

Структура std::vec::Vec имеет метод append():

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

Перемещает все элементы other в Self, оставив other пустым.

В вашем примере следующий код объединяет два вектора с помощью mutating a и b:

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

Ответ 2

Я не могу сделать это в одну строку. Дамиан Дзядуч

Это можно сделать в одну строку с помощью 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

Есть бесконечные способы.