Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Efficiently insert or replace multiple elements in the middle or at the beginning of a Vec?

Tags:

rust

Is there any straightforward way to insert or replace multiple elements from &[T] and/or Vec<T> in the middle or at the beginning of a Vec in linear time?

I could only find std::vec::Vec::insert, but that's only for inserting a single element in O(n) time, so I obviously cannot call that in a loop.

I could do a split_off at that index, extend the new elements into the left half of the split, and then extend the second half into the first, but is there a better way?

like image 498
Dogbert Avatar asked Feb 23 '15 16:02

Dogbert


People also ask

What is the most convenient way to insert a value between two elements of a vector at a given position?

The insert() method can be used to insert single or multiple elements into a given vector in different ways, for different cases. We can insert a single value at our desired position, we can even insert multiple values into the vector at once, and even we can insert a bunch of values from another vector to it.

What does VEC mean in Rust?

A contiguous growable array type, written as Vec<T> , short for 'vector'.

What is a VEC u8?

Vec<u8> is like Box<[u8]> , except it additionally stores a "capacity" count, making it three machine words wide. Separately stored capacity allows for efficient resizing of the underlying array. It's the basis for String .

How do you make a vector in Rust?

In order to initialize a vector via the new() method call, we use the double colon operator: let mut vec = Vec::new(); This call constructs a new, empty Vec<T> . The vector will not allocate until elements are pushed onto it.


1 Answers

As of Rust 1.21.0, Vec::splice is available and allows inserting at any point, including fully prepending:

let mut vec = vec![1, 5]; let slice = &[2, 3, 4];  vec.splice(1..1, slice.iter().cloned());  println!("{:?}", vec); // [1, 2, 3, 4, 5] 

The docs state:

Note 4: This is optimal if:

  • The tail (elements in the vector after range) is empty
  • or replace_with yields fewer elements than range’s length
  • or the lower bound of its size_hint() is exact.

In this case, the lower bound of the slice's iterator should be exact, so it should perform one memory move.


splice is a bit more powerful in that it allows you to remove a range of values (the first argument), insert new values (the second argument), and optionally get the old values (the result of the call).

Replacing a set of items

let mut vec = vec![0, 1, 5]; let slice = &[2, 3, 4];  vec.splice(..2, slice.iter().cloned());  println!("{:?}", vec); // [2, 3, 4, 5] 

Getting the previous values

let mut vec = vec![0, 1, 2, 3, 4]; let slice = &[9, 8, 7];  let old: Vec<_> = vec.splice(3.., slice.iter().cloned()).collect();  println!("{:?}", vec); // [0, 1, 2, 9, 8, 7] println!("{:?}", old); // [3, 4] 
like image 72
Shepmaster Avatar answered Sep 23 '22 08:09

Shepmaster