STL list, delete all the odd numbers

前端 未结 4 1362
不知归路
不知归路 2021-01-16 08:27

I am trying to learn how to work with STL and tried to write a function which will recieve a refference to a list and will try to delete all odd members. I am having a sligh

相关标签:
4条回答
  • 2021-01-16 08:55

    Method erase returns iterator to the next element after deleted. So the usual approach to such a task is the following

    void removeOdds( std::list<int> &myvector )
    {
        for ( auto it = myvector.begin(); it != myvector.end();  )
        {
            if ( *it % 2 !=0 )
            {
                it = myvector.erase( it );
            }
            else
            {
                ++it;
            }
        }
    }
    

    As for your code then the loop statement always increases the iterator

    for(list<int>::iterator p=myvector.begin(); p !=myvector.end();p++)
                                                                   ^^^^  
    

    Take into account that class std::list has methods remove and remove_if that erase all elements that satisfy the given criteria.

    Here is a demonstrative program that shows the both approaches

    #include <iostream>
    #include <list>
    
    void removeOdds( std::list<int> &myvector )
    {
        for ( auto it = myvector.begin(); it != myvector.end();  )
        {
            if ( *it % 2 !=0 )
            {
                it = myvector.erase( it );
            }
            else
            {
                ++it;
            }
        }
    }
    
    int main()
    {
        std::list<int> l = { 1, 3, 5, 2, 6, 7 };
    
        for ( auto x : l ) std::cout << x << ' ';
        std::cout << std::endl;
    
        removeOdds( l );
    
        for ( auto x : l ) std::cout << x << ' ';
        std::cout << std::endl;
    
        l = { 1, 3, 5, 2, 6, 7 };
    
        for ( auto x : l ) std::cout << x << ' ';
        std::cout << std::endl;
    
        l.remove_if( []( int x ) { return x % 2; } );
    
        for ( auto x : l ) std::cout << x << ' ';
        std::cout << std::endl;
    }
    

    The program output is

    1 3 5 2 6 7 
    2 6 
    1 3 5 2 6 7 
    2 6 
    
    0 讨论(0)
  • 2021-01-16 09:01

    Since you're learning, you better forget the 'C' way of doing things and jump directly into C++11.

    Here's your code in modern C++

    void removeOdds(vector<int>& myvector)
    {
        auto new_end = std::remove_if (myvector.begin(), myvector.end(), 
         [](const auto& value){ return value%2 !=0 }
        );    
        myvector.erase(new_end, myvector.end());
    }
    

    As far as your code goes, you can improve readability a lot just by using auto Please not that it is risky to remove elements while looping on a container. You're usually fine with a vector, but when you start using other data structures things get more nasty.

    0 讨论(0)
  • 2021-01-16 09:10

    Ok, I found one way to do this, and that was to move p++ from for loop declaration into inside it, like this.

    void removeOdds(list<int>& myvector)
    {
        for(list<int>::iterator p=myvector.begin(); p !=myvector.end();)
        {
            if(*p%2 !=0)
            {
                list<int>::iterator temp=myvector.erase(p);
                p=temp;
            }
            else
                p++;
        }
    } 
    

    Now I am curious if I can do this and still keep my for loop intact.

    0 讨论(0)
  • 2021-01-16 09:12

    The easiest way to do it would be to use std::list::remove_if. This removes elements from the list based on a unary predicate. For example,

    myvector.remove_if([](int n) { return n % 2 != 0; });
    

    The best way to work with the "STL"* is to know what is in it.

    For pre-C++11 implementations (such as the actual STL), you can pass a function:

    bool is_odd(int n) { return n % 2 != 0; }
    
    myvector.remove_if(is_odd);
    

    *"STL" means the STL but this also applies the C++ standard library

    0 讨论(0)
提交回复
热议问题