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();
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);
}
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
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 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 ;)
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
Good example to teach you check twice before hitting Post button ;)
Do not worry, happens to me all the time.
Mirek
I know, I'm a trigger happy poster :o)
> 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.
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() );
...
}
AFAIK Undefined behavior if the first element is removed (--itr will
move before the .begin()).
Mirek
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.