Let's say I have std::vector<std::pair<int,Direction>>
.
I am trying to use erase-remove_if idiom to remove pairs from the vector.
stopPoints.erase(std::remove_if(stopPoints.begin(),
stopPoints.end(),
[&](const stopPointPair stopPoint)-> bool { return stopPoint.first == 4; }));
I want to delete all pairs that have .first value set to 4.
In my example I have pairs:
- 4, Up
- 4, Down
- 2, Up
- 6, Up
However, after I execute erase-remove_if, I am left with:
- 2, Up
- 6, Up
- 6, Up
What am I doing wrong here?
clear() removes all elements from the vector leaving behind a vector of size zero while erase() deletes a single element or a range of elements from the vector.
std::remove : It doesn't actually delete elements from the container but only shunts non-deleted elements forwards on top of deleted elements. vector::erase : Removes from the vector either a single element (position) or a range of elements ([first, last)).
The correct code is:
stopPoints.erase(std::remove_if(stopPoints.begin(),
stopPoints.end(),
[&](const stopPointPair stopPoint)-> bool
{ return stopPoint.first == 4; }),
stopPoints.end());
You need to remove the range starting from the iterator returned from std::remove_if
to the end of the vector, not only a single element.
"Why?"
std::remove_if
swaps elements inside the vector in order to put all elements that do not match the predicate towards the beginning of the container. This means that if the predicate (body of the lambda function) returns true
, then that element will be placed at the end of the vector.
remove_if
then **returns an iterator which points to the first element which matches the predicate **. In other words, an iterator to the first element to be removed.
std::vector::erase
erases the range starting from the returned iterator to the end of the vector, such that all elements that match the predicate are removed.
More information: Erase-remove idiom (Wikipedia).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With