Removing elements from vector

K

kaferro

I cannot relieve that I am working on Thanksgiving, but I am stuck over
something that should be simple. I have a vector that has twenty-four
elements. I need to remove the four elements whose positions equal
zero. The code below only removes two of the four. Any ideas?

logfile << "\n\n\n. . .removing flat positions";
logfile << "vector size=" << componentPerformance.size() << endl;


int position=0;
for (vector<cPerformance>::iterator itr =
componentPerformance.begin();itr!=componentPerformance.end(); ++itr)
{
position=itr->returnPosition(); //returnPosition() returns a float
logfile << endl << itr->returnSymbol() << "Position=" <<
itr->returnPosition();
if(position==0)
{
logfile << "\tremoving. . . " << itr->returnSymbol();
componentPerformance.erase(itr);
}
}

logfile.close();
 
D

dasjotre

Use typedefs!

if cPerformance is cheep to copy:

typedef ::std::vector<cPerformance> container_t;
container_t tmp;
::std::remove_copy_if(componentPerformance.begin(),componentPerformance.end(),
::std::back_inserter(tmp),
!::boost::bind:):std::not_equal_to<int>(),
::boost::bind(&cPerformance:: returnPosition, _1), 0));

componentPerformance.swap(tmp);

if it is not cheap to copy don't
keep them in a vector,

say container_t is a list
typedef ::std::list<cPerformance> container_t;

your loop would look something like:

for(container_t::iterator it = componentPerformance.begin();
it != componentPerformance.end(); ++it)
{
if((*it). returnPosition() == 0)
it = componentPerformance.erase(it);
}
 
M

Mirek Fidler

I cannot relieve that I am working on Thanksgiving, but I am stuck over
something that should be simple. I have a vector that has twenty-four
elements. I need to remove the four elements whose positions equal
zero. The code below only removes two of the four. Any ideas?

logfile << "\n\n\n. . .removing flat positions";
logfile << "vector size=" << componentPerformance.size() << endl;


int position=0;
for (vector<cPerformance>::iterator itr =
componentPerformance.begin();itr!=componentPerformance.end(); ++itr)
{
position=itr->returnPosition(); //returnPosition() returns a float
logfile << endl << itr->returnSymbol() << "Position=" <<
itr->returnPosition();
if(position==0)
{
logfile << "\tremoving. . . " << itr->returnSymbol();
componentPerformance.erase(itr);
}
}

logfile.close();

Classic error :)

When you "erase" the element, 'itr' in fact points already to next one
(technically, in fact it is invalidated by standard AFAIK). Therefore
++itr at the end of "for" skips the element next to the removed one.

Mirek
 
M

Mirek Fidler

dasjotre said:
Use typedefs!

if cPerformance is cheep to copy:

typedef ::std::vector<cPerformance> container_t;
container_t tmp;
::std::remove_copy_if(componentPerformance.begin(),componentPerformance.end(),
::std::back_inserter(tmp),
!::boost::bind:):std::not_equal_to<int>(),
::boost::bind(&cPerformance:: returnPosition, _1), 0));

componentPerformance.swap(tmp);

No wonder nobody outside C++ ghetto considers C++ to be language
suitable to do any real work anymore :)
for(container_t::iterator it = componentPerformance.begin();
it != componentPerformance.end(); ++it)
{
if((*it). returnPosition() == 0)
it = componentPerformance.erase(it);
}

I believe this code is wrong - it skips elements past removed one.
 
D

dasjotre

Mirek said:
No wonder nobody outside C++ ghetto considers C++ to be language
suitable to do any real work anymore :)

A call for a simpler example !

inline bool operator == (cPerformance const & l, cPerformance const &
r)
{
return l.returnPosition() == r.returnPosition();
}

cPerformance nulperf(0);

::std::remove_copy(componentPerformance.begin(),componentPerformance.end(),
::std::back_inserter(tmp), nulperf);
componentPerformance.swap(tmp);

Which one would teach you more?
continue;
}
I believe this code is wrong - it skips elements past removed one.

Not any more ;)
 
D

dasjotre

dasjotre said:
A call for a simpler example !

inline bool operator == (cPerformance const & l, cPerformance const &
r)
{
return l.returnPosition() == r.returnPosition();
}

cPerformance nulperf(0);

::std::remove_copy(componentPerformance.begin(),componentPerformance.end(),
::std::back_inserter(tmp), nulperf);
componentPerformance.swap(tmp);

Which one would teach you more?


Not any more ;)

My humblest appologies.

container_t::iterator it = componentPerformance.begin();
while(it != componentPerformance.end())
{
if((*it).returnPosition() == 0)
it = componentPerformance.erase(it);
else
++it;
}

Good example to argue against hand coded loops
 
M

Mirek Fidler

container_t::iterator it = componentPerformance.begin();
while(it != componentPerformance.end())
{
if((*it).returnPosition() == 0)
it = componentPerformance.erase(it);
else
++it;
}

Good example to argue against hand coded loops

Good example to teach you check twice before hitting Post button ;)

Do not worry, happens to me all the time.

Mirek
 
L

loic-dev

I cannot relieve that I am working on Thanksgiving, but I am stuck over
something that should be simple. I have a vector that has twenty-four
elements. I need to remove the four elements whose positions equal
zero. The code below only removes two of the four. Any ideas?

The componentPerformance.erase() update the iterator to the next
element. Hence, if you still want to use your for(...) loop, you have
to change the if statement as follows:

if(position==0)
{
logfile << "\tremoving. . . " << itr->returnSymbol();
componentPerformance.erase(itr);
--itr; // because itr points to the next element.
}

HTH,
Loic.
 
S

Salt_Peter

I cannot relieve that I am working on Thanksgiving, but I am stuck over
something that should be simple. I have a vector that has twenty-four
elements. I need to remove the four elements whose positions equal
zero. The code below only removes two of the four. Any ideas?

logfile << "\n\n\n. . .removing flat positions";
logfile << "vector size=" << componentPerformance.size() << endl;


int position=0;
for (vector<cPerformance>::iterator itr =
componentPerformance.begin();itr!=componentPerformance.end(); ++itr)
{
position=itr->returnPosition(); //returnPosition() returns a float
logfile << endl << itr->returnSymbol() << "Position=" <<
itr->returnPosition();
if(position==0)
{
logfile << "\tremoving. . . " << itr->returnSymbol();
componentPerformance.erase(itr);
}
}

logfile.close();

template the functor...

#include <iostream>
#include <vector>
#include <iterator>
#include <algorithm>

struct VerifyPos0
{
bool operator()(const cPerformance& r_x)
{
// a float??
return 0 == static_cast<int>(r_x.returnPosition());
}
};

int main()
{
std::vector< cPerformance > componentPerformance;
...

componentPerformance.erase(
std::remove_if( componentPerformance.begin(),
componentPerformance.end(),
VerifyPos0()),
componentPerformance.end() );
...
}
 
M

Mirek Fidler

if(position==0)
{
logfile << "\tremoving. . . " << itr->returnSymbol();
componentPerformance.erase(itr);
--itr; // because itr points to the next element.
}

AFAIK Undefined behavior if the first element is removed (--itr will
move before the .begin()).

Mirek
 
D

Daniel T.

I cannot relieve that I am working on Thanksgiving, but I am stuck over
something that should be simple. I have a vector that has twenty-four
elements. I need to remove the four elements whose positions equal
zero. The code below only removes two of the four. Any ideas?

logfile << "\n\n\n. . .removing flat positions";
logfile << "vector size=" << componentPerformance.size() << endl;


int position=0;
for (vector<cPerformance>::iterator itr =
componentPerformance.begin();itr!=componentPerformance.end(); ++itr)
{
position=itr->returnPosition(); //returnPosition() returns a float
logfile << endl << itr->returnSymbol() << "Position=" <<
itr->returnPosition();
if(position==0)
{
logfile << "\tremoving. . . " << itr->returnSymbol();
componentPerformance.erase(itr);
}
}

logfile.close();

componentPerformance.erase( remove_if( componentPerformance.begin(),
componentPerformance.end(),
not1( mem_fun_ref( &cPerformance::returnPosition ) ) ),
componentPerformance.end() );


Or if you have/want to write it out:

vector<cPerformance>::iterator begin = componentPerformance.begin();
vector<cPerformance>::iterator end = componentPerformance.end();
vector<cPerformance>::iterator pos = componentPerformance.begin();
while ( begin != end ) {
if ( begin->returnSymbol() == 0.0 )
++begin;
else
*pos++ = *begin++;
}
componentPerformance.erase( pos, end );
 

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
473,764
Messages
2,569,564
Members
45,040
Latest member
papereejit

Latest Threads

Top