Как объединить неизменяемые векторы в одну строку? - PullRequest
0 голосов
/ 25 ноября 2018

У меня есть неизменяемые векторы a и b, где элементы дешевы для копирования, и я хочу создать вектор, который формирует конкатенацию этих существующих векторов без их изменения (*).

Более ранний вопрос касался его, если один из векторов является изменяемым , поэтому очевидным ответом является первый вектор клона a, например,

let mut r = a.clone();
r.extend(&b);

, но это не кажется ни изящным, ни эффективным (расширениеможет легко вызвать одно ненужное перераспределение, верно?). (исправленная) лучшая альтернатива I (будучи нубом 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
}

Поскольку копировать элементы дешево, ответ на более общий вопрос для векторов строк должен применяться здесь, но vec![a, b].concat(), кажется, работает, только если вы строите вектор векторов, перемещая в него векторы, потому что vec![&a, &b].concat() выдает «метод с именем concat found».

Существует ли однострочник для этой, казалось бы, простой работы, даже если она не оптимальна?


(*) оказывается, что есть два значения слова "без изменений":

  • просто неизменный, что в Rust означает, что если код компилируется, он не увидит переменную с измененным значением;но переменная может быть удалена, и дальнейший или будущий код больше не сможет ее использовать
  • фактически только для чтения, оставляя переменную нетронутой для дальнейшего или будущего кода

Ответы [ 2 ]

0 голосов
/ 26 ноября 2018

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));
}
0 голосов
/ 25 ноября 2018

Примечание редактора: ОП изменили свой вопрос после предоставления этого ответа.Обратитесь к версии вопроса , из которой был создан этот ответ.

Ваш первый пример на самом деле не имеет смысла.Вы упоминаете неизменность, но поскольку вы передаете владение векторами функции 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()
}

См. также:

...