-
May 18th, 2011, 02:06 PM
#1
remove multiple elements from vector in a loop
I have a vector,
Code:
std::vector<int> myVector;
myVector[0] = 3;
myVector[1] = 4;
myVector[2] = 5;
and I need to remove certain elements, in this case [1] and [2]. This is happening in a loop where some things are evaluated, and under certain circumstances, and element is removed.
Code:
for(i=0; i<myVector.size(); i++) {
if(myVector[i] == 4 || myVector[i] == 5) {
myVector.erase( myVector.begin()+i );
}
}
the logic is simplified here. The output after this loop is,
myVector.size() = 2
myVector[0] = 3;
myVector[1] = 5;
As I read this, when myVector[i] == 3, control falls through and nothing happens. When myInt[i] == 4, myVector.begin()+i = 0+1 and myVector[1] is erased. When myVector[i] == 5, myVector.begin()+i = 0+2 and myVector[2] is erased. Element [2] doesn't exist anymore, so the value 5 remains on the list. Obviously I'm not using the iterator properly.
The iterator position needs to be dynamic to take into account the changing size of the vector, but I can't see how to do that. This seems like a simple issue, so I presume I am missing something here. I can't just loop through and look for 4 or 5, the logic is more complex than that. I need to know how to recursively remove elements from a vector, taking into account the fact that the vector size changes.
Maybe I need to loop differently. It's almost like I need to repeat the value of i in a case where a given i was removed. This has to work in larger vectors where the elements to be removed can occur in any element. I guess I could just set i=0 after each element is removed and repeat from the top, but that doesn't seem like the best solution either.
LMHmedchem
Last edited by LMHmedchem; May 18th, 2011 at 02:10 PM.
-
May 18th, 2011, 02:14 PM
#2
Re: remove multiple elements from vector in a loop
Didn't read the whole post, so sorry if this is the wrong answer, but when removing items in a loop from an index based container, it's easiest to start at the end and work backwards.
-
May 18th, 2011, 02:17 PM
#3
Re: remove multiple elements from vector in a loop
Vlad - MS MVP [2007 - 2012] - www.FeinSoftware.com
Convenience and productivity tools for Microsoft Visual Studio:
FeinWindows - replacement windows manager for Visual Studio, and more...
-
May 18th, 2011, 03:16 PM
#4
Re: remove multiple elements from vector in a loop
see the following post on using remove_if and removing elements
while looping.
http://www.codeguru.com/forum/showthread.php?t=475058
-
May 18th, 2011, 03:47 PM
#5
Re: remove multiple elements from vector in a loop
So it would appear I could do something like,
Code:
int remove;
for(i=0; i<myVec.size(); i++) {
if(myVec[i] == 4 || myVector[i] == 5) {
remove_this = myVector[i];
myVec.erase( remove(myVec.begin(),myVec.end(),remove_this) , myVec.end() );
}
}
This seems to have the same problem as the first code I posted.
myVector.size() = 2
myVector[0] = 3;
myVector[1] = 5;
LMHmedchem
-
May 18th, 2011, 03:52 PM
#6
Re: remove multiple elements from vector in a loop
Code:
myVec.erase(
std::remove_if(myVec.begin(),myVec.end(), [](int i) { return i == 4 || i == 5; }),
myVec.end());
Or you can create an appropriate function or functor if your compiler does not support the lambda function I used above.
-
May 18th, 2011, 04:17 PM
#7
Re: remove multiple elements from vector in a loop
Originally Posted by Lindley
Code:
myVec.erase(
std::remove_if(myVec.begin(),myVec.end(), [](int i) { return i == 4 || i == 5; }),
myVec.end());
Or you can create an appropriate function or functor if your compiler does not support the lambda function I used above.
My complier doesn't like this, I get
expected primary-expression before '[' token
expected primary-expression before ']' token
expected primary-expression before "int"
It seems as if I need a function that returns the values for what I need to remove?
LMHmedchem
-
May 18th, 2011, 05:16 PM
#8
Re: remove multiple elements from vector in a loop
geez. you mean like this? Lindley did say that the lamda expression might not work for you. In that case write a global function, static member function of a class, or a functor.
Code:
// write a global function
void RemoveTheseValues
{
return(i == 4 || i == 5);
}
// or write a functor
struct RemoveTheseValues
{
bool operator() (int i)
{
return(i == 4 || i == 5);
}
};
See here for even more examples.
http://www.cplusplus.com/reference/algorithm/remove_if/
-
May 18th, 2011, 05:22 PM
#9
Re: remove multiple elements from vector in a loop
Well I'm going to have to go with this, for lack of being able to get anything else working,
Code:
for(i=0; i<myVector.size(); i++) {
if(myVector[i] == 4 || myVector[i] == 5) {
int remove = myVector[i];
myVector.erase( remove(myVector.begin(), myVector.end(), remove), myVector.end() );
i = 0;
}
}
It will cost an extra iteration through the loop or so, but these vecs will never have more than two or three elements. Perhaps I should have just looked at removing elements starting from the back of the vector as GCDEF suggested.
Originally Posted by kempofighter
geez. you mean like this? Lindley did say that the lamda expression might not work for you. In that case write a global function, static member function of a class, or a functor.
Code:
// write a global function
void RemoveTheseValues
{
return(i == 4 || i == 5);
}
// or write a functor
struct RemoveTheseValues
{
bool operator() (int i)
{
return(i == 4 || i == 5);
}
};
See here for even more examples.
http://www.cplusplus.com/reference/algorithm/remove_if/
I tried quite a few versions of things like this, but I couldn't get any of them to compile. I just can't spend all afternoon trying to improve on something this simple. It would be nice if there was a version of the stl documentation that wasn't written in ancient Greek. Maybe I'm just a moron, but I don't find things like, "Unary predicate taking an element in the range as argument, and returning a value indicating the falsehood (with false, or a zero value) or truth (true, or non-zero) of some condition applied to it. This can either be a pointer to a function or an object whose class overloads operator()" to be very helpful if you weren't a CS major, which I wasn't. English is a nice language too.
LMHmedchem
Last edited by LMHmedchem; May 18th, 2011 at 05:30 PM.
-
May 18th, 2011, 05:23 PM
#10
Re: remove multiple elements from vector in a loop
Originally Posted by LMHmedchem
So it would appear I could do something like,
Code:
int remove;
for(i=0; i<myVec.size(); i++) {
if(myVec[i] == 4 || myVector[i] == 5) {
remove_this = myVector[i];
myVec.erase( remove(myVec.begin(),myVec.end(),remove_this) , myVec.end() );
}
}
This seems to have the same problem as the first code I posted.
myVector.size() = 2
myVector[0] = 3;
myVector[1] = 5;
LMHmedchem
The problem is obviously that you are still decreasing the size of the vector within the loop. Don't do that. The loop will end up terminating before all of the values are tested. When the loop tests the size again, it'll be shorter.
-
May 18th, 2011, 05:32 PM
#11
Re: remove multiple elements from vector in a loop
Originally Posted by LMHmedchem
Well I'm going to have to go with this, for lack of being able to get anything else working,
Code:
for(i=0; i<myVector.size(); i++) {
if(myVector[i] == 4 || myVector[i] == 5) {
int remove = myVector[i];
myVector.erase( remove(myVector.begin(), myVector.end(), remove), myVector.end() );
i = 0;
}
}
It will cost an extra iteration through the loop or so, but I can't spend all afternoon trying to improve on something this simple. Perhaps I should have just looked at removing elements starting from the back of the vector as GCDEF suggested.
LMHmedchem
It really is not that hard to tweak what lindley posted. All you have to do is write the global function and substitute its name where the lamda expression went (that is the 3rd argument to remove_if). It's that simple. If you can't do that in 10 minutes then you deserve an F on your assignment.
-
May 18th, 2011, 05:33 PM
#12
Re: remove multiple elements from vector in a loop
Originally Posted by kempofighter
The problem is obviously that you are still decreasing the size of the vector within the loop. Don't do that. The loop will end up terminating before all of the values are tested. When the loop tests the size again, it'll be shorter.
I tried storing the values to remove in another vector, but of course I ended up looping though that as well. I need one of these remove_if methods that I can pass a range to and a value to remove, but no joy so far on that.
LMHmedchem
-
May 18th, 2011, 05:35 PM
#13
Re: remove multiple elements from vector in a loop
Originally Posted by LMHmedchem
Well I'm going to have to go with this, for lack of being able to get anything else working,
Code:
for(i=0; i<myVector.size(); i++) {
if(myVector[i] == 4 || myVector[i] == 5) {
int remove = myVector[i];
myVector.erase( remove(myVector.begin(), myVector.end(), remove), myVector.end() );
i = 0;
}
}
It will cost an extra iteration through the loop or so, but these vecs will never have more than two or three elements. Perhaps I should have just looked at removing elements starting from the back of the vector as GCDEF suggested.
I tried quite a few versions of things like this, but I couldn't get any of them to compile. I just can't spend all afternoon trying to improve on something this simple. It would be nice if there was a version of the stl documentation that wasn't written in ancient Greek. Maybe I'm just a moron, but I don't find things like, "Unary predicate taking an element in the range as argument, and returning a value indicating the falsehood (with false, or a zero value) or truth (true, or non-zero) of some condition applied to it. This can either be a pointer to a function or an object whose class overloads operator()" to be very helpful if you weren't a CS major, which I wasn't. English is a nice language too.
LMHmedchem
Did you look at the example? You could have copy and pasted the example from that link and compiled it. Simply substitute your function names.
-
May 18th, 2011, 05:59 PM
#14
Re: remove multiple elements from vector in a loop
Originally Posted by LMHmedchem
I have a vector,
Code:
std::vector<int> myVector;
myVector[0] = 3;
myVector[1] = 4;
myVector[2] = 5;
and I need to remove certain elements, in this case [1] and [2]. This is happening in a loop where some things are evaluated, and under certain circumstances, and element is removed.
Code:
#include <algorithm>
#include <vector>
#include <iostream>
bool RemoveMe(int val)
{
return ( val == 3 || val == 4);
}
int main()
{
std::vector<int> vect(3);
vect[0] = 3;
vect[1] = 4;
vect[2] = 5;
vect.erase(std::remove_if(vect.begin(), vect.end(), RemoveMe), vect.end());
for (size_t i = 0; i < vect.size(); ++i )
std::cout << vect[i] << "\n";
}
Is this what you're trying to code?
But in general, if you're writing convoluted loops to remove elements from a container in C++, then you need to take a step back and rethink what you're doing, as more than likely, an alogrithm or set of algorithm functions will do the job, safely and correctly.
Regards,
Paul McKenzie
-
May 18th, 2011, 10:00 PM
#15
Re: remove multiple elements from vector in a loop
Originally Posted by LMHmedchem
It would be nice if there was a version of the stl documentation that wasn't written in ancient Greek. Maybe I'm just a moron, but I don't find things like, "Unary predicate taking an element in the range as argument, and returning a value indicating the falsehood (with false, or a zero value) or truth (true, or non-zero) of some condition applied to it. This can either be a pointer to a function or an object whose class overloads operator()" to be very helpful if you weren't a CS major, which I wasn't. English is a nice language too.
You just have to get used to the terminology. All me to translate:
"Unary predicate (function taking one argument) taking an element in the range as argument (the function's argument type must match the type in the container), and returning a value indicating the falsehood (with false, or a zero value) or truth (true, or non-zero) of some condition applied to it (the function must return a bool indicating whether or not to remove the element in question). This can either be a pointer to a function or an object whose class overloads operator() (You can specify the function several different ways.)"
Such formal language can have a learning curve, but its preciseness is useful when you want to know exactly what a container or algorithm is going to do.
Last edited by Lindley; May 18th, 2011 at 10:02 PM.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|