How to remove elements of vector by index

A

Angus

Hello

I have a vector<int> (aRemovecoll) which is a list of the indexes to
be removed from another vector. The other vecotr contains an object -
I will call it SomeObject. So the other vecotr is a
vector<SomeObject>.

I have created a function like this so far:

UINT uNumElements = aRemoveColl.GetSize();
vector<T>::reverse_iterator obCurrent = rbegin(); // work from
end back
for (UINT nLoop = uNumElements; nLoop != 0; nLoop--)
{
// Work from end of vecotr to beginning so that iterators are
always valid
intuIndex;
aRemoveColl.GetAt(nLoop, uIndex);
advance(obCurrent, uIndex);
erase(obCurrent);
}

My thinking is that I need to erase from the end backwards because
otherwise the iterator will become invalid. But then advance doesn't
see right. Is there a backward? Or should I be doing this totally
differently?
 
O

Ondra Holub

Hello

I have a vector<int> (aRemovecoll) which is a list of the indexes to
be removed from another vector. The other vecotr contains an object -
I will call it SomeObject. So the other vecotr is a
vector<SomeObject>.

I have created a function like this so far:

UINT uNumElements = aRemoveColl.GetSize();
vector<T>::reverse_iterator obCurrent = rbegin(); // work from
end back
for (UINT nLoop = uNumElements; nLoop != 0; nLoop--)
{
// Work from end of vecotr to beginning so that iterators are
always valid
intuIndex;
aRemoveColl.GetAt(nLoop, uIndex);
advance(obCurrent, uIndex);
erase(obCurrent);
}

My thinking is that I need to erase from the end backwards because
otherwise the iterator will become invalid. But then advance doesn't
see right. Is there a backward? Or should I be doing this totally
differently?

Hi.

You can use iterators, for example:
std::vector<int> v;

// Here fill v with some values
// ...

v.erase(v.begin() + 4, v.begin() + 10); // Removes elements from index
4 to 10
 
J

James Kanze

I have a vector<int> (aRemovecoll) which is a list of the indexes to
be removed from another vector. The other vecotr contains an object -
I will call it SomeObject. So the other vecotr is a
vector<SomeObject>.
I have created a function like this so far:
UINT uNumElements = aRemoveColl.GetSize();
vector<T>::reverse_iterator obCurrent = rbegin(); // work from
end back
for (UINT nLoop = uNumElements; nLoop != 0; nLoop--)
{
// Work from end of vecotr to beginning so that iterators are
always valid
intuIndex;
aRemoveColl.GetAt(nLoop, uIndex);
advance(obCurrent, uIndex);
erase(obCurrent);
}
My thinking is that I need to erase from the end backwards because
otherwise the iterator will become invalid.

Not really.
But then advance doesn't see right.

I don't really understand your code. What's GetAt, for example?
The easiest way to do this would be something like:

for ( std::vector< int >::const_iterator it =
aRemoveColl.begin() ;
it != aRemoveColl.end() ;
++ it ) {
data.erase( data.begin() + *it ) ;
}

You don't remove anything from the vector you're iterating over,
so there is no problem.

Note however that this is O(n*m), with n the number of elements
of data, and m the number of elements to be erased. So you
might want to consider generating into a new vector, or even
defining a predicate for remove_if, and using it. (If
aRemoveColl is sorted, something along the lines of:

class SomeObject ;

class IndexIn
{
public:
typedef std::vector< size_t >
IndexTable ;
typedef std::vector< size_t >::const_iterator
IndexIter ;

explicit IndexIn( IndexTable const& indexes )
: myImpl( new Impl( indexes.begin(), indexes.end() ) )
{
}
bool operator()( SomeObject const& ) const
{
return (*myImpl)() ;
}

private:
class Impl
{
public:
Impl( IndexIter begin, IndexIter end )
: myCurrent( begin )
, myEnd( end )
, myIndex( 0 )
{
}
bool operator()()
{
bool result
= myCurrent != myEnd && myIndex == *myCurrent ;
++ myIndex ;
if ( result ) {
++ myCurrent ;
}
return result ;
}
private:
IndexIter myCurrent ;
IndexIter myEnd ;
size_t myIndex ;
} ;

boost::shared_ptr< Impl>
myImpl ;
} ;

// ...
v.erase( std::remove_if( v.begin(), v.end(),
IndexIn( aRemoveColl ) ),
v.end() ) ;

should do the trick.)
Is there a backward? Or should I be doing this totally
differently?

I'd do it differently.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,434
Messages
2,571,685
Members
48,796
Latest member
Greg L.

Latest Threads

Top