I have a vector full of strings
the vector consistentWords contains 4 strings
- dedf
- eedf
- fedf
- hedf
Now I want to delete all the strings that words don't start with the letter d
However it ends up just deleting eedf and hedf and the result I have left is
- dedf
- fedf
My code:
for(int q=0; q<consistentWords.size(); q++)
{
string theCurrentWord = consistentWords[q];
if(theCurrentWord[0] != 'd')
{
consistentWords.erase(consistentWords.begin()+q);
}
}
Any thoughts? I just can't see why it's not deleting all of the strings that don't start with d.
The problem is you are deleting elements from the vector and incrementing your index q
in the same iteration. So in the 2nd iteration of your for loop, you erase "eedf"
from you vector then your vector is ["dedf", "fedf", "hedf"]
and q = 1
. But then when you loop back to the begining of the for loop, q
is incremented to 2 so you look at "hedf"
next, skipping "fedf"
. To fix this you could decrement q
when you remove an element from the array like so:
for(int q=0; q<consistentWords.size(); q++)
{
string theCurrentWord = consistentWords[q];
if(theCurrentWord[0] != 'd')
{
consistentWords.erase(consistentWords.begin()+q);
--q;
}
}
Or you could use iterators:
vector<string>::iterator it = consistentWords.begin()
while(it != consistentWord.end())
{
string theCurrentWord = consistentWords[q];
if(theCurrentWord[0] != 'd')
{
it = consistentWords.erase(it);
}
else
{
++it;
}
}
Note that erase
returns an iterator to the element after the one you have erased. You must re-assign it
because it becomes invalidated when the vector is resized.
To start with, the strings correspond to these indices:
dedf 0
eedf 1
fedf 2
hedf 3
Let's say you delete eedf
(so q == 1
. After the delete, the vector looks like
dedf 0
fedf 1
hedf 2
But then q
gets incremented to 2, completely skipping over fedf
. The fix would be to alter the for
loop slightly:
for(int q=0; q<consistentWords.size();)
{
string theCurrentWord = consistentWords[q];
if(theCurrentWord[0] != 'd')
{
consistentWords.erase(consistentWords.begin()+q);
}
else
{
q++;
}
}
or something to the same effect.
You are skipping elements. Assume you need to delete elements 5,6:
when you delete element 5, element 6 becomes element 5 - and you skip it, since q
was increased to 6,
The better way to do it is manually increasing q
only when you do not delete an element
When you erase you should not do q++. Then you miss one element.
The question has been answered, but you should look into the Erase-remove idiom:
Example:
consistentWords.erase(
std::remove_if(consistentWords.begin(), consistentWords.end(),
[](const std::string& s) -> bool { return (s[0] == 'd'); }),
consistentWords.end());
To remove the word:
consistentWords.erase(
std::remove(consistentWords.begin(), consistentWords.end(), theCurrentWord),
consistentWords.end()
);