How to set a Vec to a subslice of itself?

Basically, I want to do this:

Convert this Vec:
[1, 2, 3, 4, 5, 6] to: [2, 3, 4] without cloning anything.

Ideally, a method like vec.resize_at(index, length) or something would be nice.

I guess with a signature of something like
pub fn resize_at(self, index: usize, length: usize) -> Vec<T>, where it consumes the original Vec but doesn't clone it.

1 Like

Remove the end, then remove the beginning:

    v.truncate(4);
    v.drain(..1);

https://play.rust-lang.org/?edition=2018&gist=06607be08a3ae2a6862df9955b6cd3ed

(you could also use a retain with a stateful predicate, but that seems like more code for no gain.)

1 Like

Oh, cool, thanks! I'll definitely use this, but out of curiosity, there's no way to give back the old memory to the OS? (Coming from C, I'm thinking about realloc)

you probably want https://doc.rust-lang.org/std/vec/struct.Vec.html#method.shrink_to_fit

Most Vec methods don't deallocate because that causes major performance issues in certain use cases.

If you really want to release extra memory early, you can call https://doc.rust-lang.org/std/vec/struct.Vec.html#method.shrink_to_fit. (But don't bother unless you'll keep the Vec around for quite a while after shrinking it, won't grow it again, and the shrink is substantial.)

3 Likes

BTW, No matter how you do it, you can't change the start position without cloning or moving the elements.

[1, 2, 3, 4, 5, 6] to [1, 2, 3, 4] is cheap and easy with truncate(). But Vec holds the pointer to the start of the data, and it must be the pointer that is used to free the memory. Giving pointer+1 to the allocator would crash it, and Vec doesn't have room to remember that +1 offset. So the only way to move the start is to copy or reallocate.

You can take a slice [1..4] at zero cost, leaving Vec's mem as-is. And if you want to free the remaining memory, there's hardly any difference between truncate/drain/shrink_to_fit combos and just vec[1..4].to_owned().

4 Likes

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.