My aim was to try a solution for this question:Removing all empty elements in a vector from end. using erase-remove idiom.
The idea is to remove all elements starting from the end which are empty (equal to white-space) in a given a std::vector<std::string>
of strings. The removal of elements should stop when a non-empty element is found.
Example:
vec = { " ", "B", " ", "D", "E", " ", " ", " " };
After the removal:
vec = { " ", "B", " ", "D", "E"};
Here is the solution I tried:
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <iterator>
int main()
{
std::vector<std::string> vec = { " ", "B", " ", "D", "E", " ", " ", " " };
bool notStop = true;
auto removeSpaceFromLast = [&](const std::string& element)-> bool
{
if(element != " " ) notStop = false;
return ( (element == " ") && (notStop) );
};
vec.erase(
std::remove_if(vec.rbegin(), vec.rend(), removeSpaceFromLast),
vec.rend() );
std::copy(vec.begin(), vec.end(), std::ostream_iterator<std::string>(std::cout,","));
return 0;
}
This gave me an error:
no matching function for call to std::vector<std::__cxx11::basic_string<char> >::erase(std::reverse_iterator<__gnu_cxx::__normal_iterator<std::__cxx11::basic_string<char>*, std::vector<std::__cxx11::basic_string<char> > > >, std::vector<std::__cxx11::basic_string<char> >::reverse_iterator)'|
Then I read about working of std::vector::erase()
here: Does vector::erase not work with reverse iterators?
And changed the code:
vec.erase(
std::remove_if(vec.rbegin().base(), vec.rend().base(), removeSpaceFromLast),
vec.rend().base() );
This time it compiled, but gave me the output = original vector.
Can anybody explanine:
Returns a reverse iterator pointing to the last element in the vector (i.e., its reverse beginning). Reverse iterators iterate backwards: increasing them moves them towards the beginning of the container. rbegin points to the element right before the one that would be pointed to by member end.
An element can be removed from a Collection using the Iterator method remove(). This method removes the current element in the Collection. If the remove() method is not preceded by the next() method, then the exception IllegalStateException is thrown.
You miss-placed the calls to base()
. remove_if
will move all spaces it found starting from the end to the beginning part of the vector (as it would move spaces found starting from the beginning move towards the end if forward iterators were used) and returns the iterator pointing to the end position of the to-be-erased sequence (i.e. the begin of the space to be kept, as we reversed the iterator meanings), i.e.:
" ", " ", " ", "B", " ", "D", "E"
Then, you have to erase from the beginning, i.e. rend().base()
.
vec.erase(vec.rend().base(),
std::remove_if(vec.rbegin(), vec.rend(), removeSpaceFromLast).base()
);
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