Link to home
Start Free TrialLog in
Avatar of mattososky
mattososky

asked on

erasing out of an vector...

I want to iterate through a vector, process some logic on the items determining whether they still belong in the vector. But I'm having trouble figuring out how.

While iterating through, if it's decided that vector element should be remove, you can't erase it right there, because then you cannot contiue iterating the rest of the vector. You would need to contruct a new vector and start over. I thought about saving the index of the vector item I want to remove and erasing them afterwards, but that wont work becase the the item indices will change after I remove the first one.

Any thoughts on how I can swiftly accomplish this?
Avatar of evilrix
evilrix
Flag of United Kingdom of Great Britain and Northern Ireland image

Have you considered using a std::list instead? You can remove items from a list without invalidating the iterators.
SOLUTION
Avatar of evilrix
evilrix
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of mattososky
mattososky

ASKER

Something I'll look into later, but at this point I'm commited to using the vector, so i need a solution with it.
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
then would make the itr = vector.end and itr-- until it equals vector.begin?

this isnt working...

deletes the first pass, fails at the second with 'vector iterators incompatible'
vector<string*> str_vector;
	for(int i = 0;i<5;i++)
	{
		string* s = new string("YOYO");
		str_vector.push_back(s);
	}
 
	vector<string*>::iterator itr = str_vector.end();
 
	while(itr!=str_vector.begin())
	{
		itr--;
		str_vector.erase(itr);
	}

Open in new window

>> then would make the itr = vector.end and itr-- until it equals vector.begin?
Traversing in reverse using forward iterators is tricky and you can't use reverse iterators to erase so you'll have to use indexes...
#include <iostream>
#include <vector>
#include <algorithm>
 
int gen()
{
	static int i = -1;
	return ++i;
}
 
typedef std::vector<int> intvec_t;
 
int main()
{
	intvec_t intvec(10);
 
	std::generate(intvec.begin(), intvec.end(), gen);
 
	std::cout << "Display all numbers and remove odd" << std::endl;
 
	intvec_t::size_type st = (intvec.size() - 1);
 
	do
	{
		std::cout << intvec[st] << std::endl;
		if(intvec[st]%2) { intvec.erase(intvec.begin() + st); }
		--st;
	}
	while(st > 0);
 
	std::cout << std::endl << "After all odd items were rmeoved" << std::endl;
	std::copy(intvec.begin(), intvec.end(), std::ostream_iterator<int>(std::cout, "\n"));
}

Open in new window

>> string* s = new string("YOYO");
Why push back pointers to string, it can safely be copied into the vector? Putting heap allocated memory into vectors is always problematic... it creates very hard to protect against leakage issues with exceptions.
>>You would need to contruct a new vector and start over.

You won't need a new vector - and a little trick will help:
#include <vector>
#include <iostream>
using namespace std;
 
void main () {
 
  int tmp[] = { 1,2,3,4,3,2,5,2};
  vector<int> v(&tmp[0],&tmp[7]);
 
  int offs = 0;
 
  vector<int>::iterator i = v.begin();
 
  for (i = v.begin(); i != v.end(); ++i) cout << *i << " ";
 
  i = v.begin();
 
  while(i != v.end()) {
 
    if (*i == 2) { v.erase(i); i = v.begin() + offs; continue;}
 
    ++i;
    ++offs;
  }
  
 
  cout << endl;
  for (i = v.begin(); i != v.end(); ++i) cout << *i << " ";
}

Open in new window

this was just a test. I needed to replicate what my real application is doing. I in placeing pointers in there because this is not the only reference to these objects..