Removing elements from vector

Discussion in 'C++' started by kaferro@hotmail.com, Nov 23, 2006.

  1. Guest

    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();
     
    , Nov 23, 2006
    #1
    1. Advertising

  2. dasjotre Guest

    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);
    }
     
    dasjotre, Nov 23, 2006
    #2
    1. Advertising

  3. Mirek Fidler Guest

    wrote:
    > 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
     
    Mirek Fidler, Nov 23, 2006
    #3
  4. Mirek Fidler Guest

    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.
     
    Mirek Fidler, Nov 23, 2006
    #4
  5. dasjotre Guest

    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, Nov 23, 2006
    #5
  6. dasjotre Guest

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


    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
     
    dasjotre, Nov 23, 2006
    #6
  7. Mirek Fidler Guest


    > 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
     
    Mirek Fidler, Nov 23, 2006
    #7
  8. dasjotre Guest

    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 :eek:)
     
    dasjotre, Nov 23, 2006
    #8
  9. Guest

    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.
     
    , Nov 23, 2006
    #9
  10. Salt_Peter Guest

    wrote:
    > 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() );
    ...
    }
     
    Salt_Peter, Nov 23, 2006
    #10
  11. Mirek Fidler Guest

    > 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
     
    Mirek Fidler, Nov 23, 2006
    #11
  12. Daniel T. Guest

    In article <>,
    wrote:

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

    --
    To send me email, put "sheltie" in the subject.
     
    Daniel T., Nov 24, 2006
    #12
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Helge Richter

    Removing Elements from a Vector

    Helge Richter, Feb 27, 2004, in forum: Java
    Replies:
    5
    Views:
    6,432
    Andrew Hobbs
    Feb 28, 2004
  2. Tino
    Replies:
    1
    Views:
    8,913
    Jonathan Turkanis
    Feb 20, 2004
  3. Jason Heyes
    Replies:
    6
    Views:
    8,391
    Jason Heyes
    Nov 16, 2004
  4. Adam Hartshorne
    Replies:
    2
    Views:
    381
    Nitin Motgi
    Jan 27, 2006
  5. Replies:
    8
    Views:
    1,960
    Csaba
    Feb 18, 2006
Loading...

Share This Page