'Is there a simliar function used to split one vec into two and keep the last elements?

We know that Vec provides split_off() function to split the slice into two. I wonder if there is a similar function that splits the original Vec, but keeps the back part and returns the front part as a new Vec directly?



Solution 1:[1]

While a vec.split_off_front(n), is not provided, you can use the more general drain instead:

vec.drain(0..n).collect::<Vec<_>>()

Playground

I do not know for a fact why split_off is part of std, but split_off_front is not. A possible reason I can imagine is that it cannot be done as efficiently. For a split_off_front to keep the elements after n in self, it would have to copy the elements in 0..n to a new vector, and then move the remaining elements from n.. to 0.., because vectors must always be filled from element 0.

Contrary, split_at only needs to copy the elements its splitting off the original vector.

If you want to cheaply remove elements from the front of something, use a Deque.

Solution 2:[2]

You can implement split_off_front by combining split_off and swap:

fn split_off_front<T>(vec: &mut Vec<T>, at: usize) -> Vec<T> {
    let mut split = vec.split_off(vec.len() - at - 1);
    std::mem::swap(vec, &mut split);
    split
}

I think this is in theory better than drain since only the elements at the end are moved.


You can also implement it with split_off and rotate_left:

fn split_off_front<T>(vec: &mut Vec<T>, at: usize) -> Vec<T> {
    vec.rotate_left(at);
    vec.split_off(vec.len() - at)
}

I think this is in theory worse than drain since it requires moving the front elements twice.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2