Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Removing elements from vector

1 view
Skip to first unread message

kaf...@hotmail.com

unread,
Nov 23, 2006, 11:16:44 AM11/23/06
to
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();

dasjotre

unread,
Nov 23, 2006, 11:39:44 AM11/23/06
to
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);
}

Mirek Fidler

unread,
Nov 23, 2006, 12:11:36 PM11/23/06
to

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

Mirek Fidler

unread,
Nov 23, 2006, 12:15:07 PM11/23/06
to

dasjotre wrote:
> 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.

dasjotre

unread,
Nov 23, 2006, 12:43:21 PM11/23/06
to

Mirek Fidler wrote:

> dasjotre wrote:
> > 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 :)

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?

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

continue;


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

Not any more ;)

dasjotre

unread,
Nov 23, 2006, 12:54:30 PM11/23/06
to

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

Mirek Fidler

unread,
Nov 23, 2006, 12:57:46 PM11/23/06
to

> 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

dasjotre

unread,
Nov 23, 2006, 1:04:24 PM11/23/06
to

Mirek Fidler wrote:
> > 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 ;)
>

I know, I'm a trigger happy poster :o)

loic...@gmx.net

unread,
Nov 23, 2006, 1:18:42 PM11/23/06
to
kaf...@hotmail.com schrieb:

> 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.

Salt_Peter

unread,
Nov 23, 2006, 1:18:57 PM11/23/06
to

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() );
...
}

Mirek Fidler

unread,
Nov 23, 2006, 4:35:20 PM11/23/06
to
> 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

Daniel T.

unread,
Nov 23, 2006, 10:01:53 PM11/23/06
to
In article <1164298604.4...@k70g2000cwa.googlegroups.com>,
kaf...@hotmail.com wrote:

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 );

--
To send me email, put "sheltie" in the subject.

0 new messages