Remove the Last Element of a Vector

remove the last element of a vector

You can use negative offsets in head (or tail), so head(x, -1) removes the last element:

R> head( 1:4, -1)
[1] 1 2 3
R>

This also saves an additional call to length().

Edit: As pointed out by Jason, this approach is actually not faster. Can't argue with empirics. On my machine:

R> x <- rnorm(1000)
R> microbenchmark( y <- head(x, -1), y <- x[-length(x)], times=10000)
Unit: microseconds
expr min lq median uq max
1 y <- head(x, -1) 29.412 31.0385 31.713 32.578 872.168
2 y <- x[-length(x)] 14.703 15.1150 15.565 15.955 706.880
R>

Segmentation fault on erasing the last element from the vector C++

The problem is that std::vector::end returns an iterator to the element following the last element of the container, not to the last element.

What you want should be

vec.erase(vec.end() - 1); // trying to erase the last element of vec

Remove last n elements of vectorint in O(1) complexity C++?

The C++ standard (I believe) says that the cost of removing k items from the end of a std::vector must have time complexity O(k), but that's an upper bound on the amount of work done, not a lower bound.

The C++ compiler, when generating code for std::vector<int>::erase, can inspect the types and realize that there's no need to do any per-element work when removing ints; it can just adjust the logical size of the std::vector and call it a day. In fact, it looks like g++, with optimization turned on, does just that. The generated assembly here doesn't involve any loops and simply changes the size of the std::vector.

If you don't want to rely on the compiler to do this, another option would be to store your own separate size variable and then just "pretend" that you've removed items from the std::vector by never using them again. That takes time O(1).

Hope this helps!

taking the last element of a vector and moving it to another vector

You are passing the vectors by value, so you are acting on copies of the vectors, not on the original vectors. You need to pass the vectors by reference instead.

Also, you said you wanted to move the last element, but you are actually moving the first element instead. And you are not removing the element from the old vector.

Also, there is no need to use std::move() with raw pointers. Why are you using ball* at all? You should be using std::unique_ptr<ball> instead.

Try something more like this:

void move(std::vector<ball*> &ball_box, std::vector<ball*> &n_ball_box)
{
ball* b = ball_box.back();
ball_box.pop_back();
n_ball_box.push_back(b);
}

If you really want to move the first element, then it would look like this instead:

void move(std::vector<ball*> &ball_box, std::vector<ball*> &n_ball_box)
{
ball* b = ball_box.front();
ball_box.erase(ball_box.begin());
n_ball_box.push_back(b);
}

That said, if you switch to std::unique_ptr<ball>, then it would look more like this:

using ball_ptr = std::unique_ptr<ball>;

void move(std::vector<ball_ptr> &ball_box, std::vector<ball_ptr> &n_ball_box)
{
ball_ptr b = std::move(ball_box.back());
ball_box.pop_back();
/* or:
ball_ptr b = std::move(ball_box.front());
ball_box.erase(ball_box.begin());
*/
n_ball_box.push_back(std::move(b));
}

std::vector<ball_ptr> old_balls;
std::vector<ball_ptr> new_balls;
...
move(old_balls, new_balls);


Related Topics



Leave a reply



Submit