【问题标题】:remove elements with specific value from std::list从 std::list 中删除具有特定值的元素
【发布时间】:2010-10-15 05:49:24
【问题描述】:

我需要从 std::list 中删除具有特定值的元素。对于list<int>,我使用了 remove() 方法。

现在我有了list<CMyClass>,所以我想我应该使用 remove_if() 但它的谓词只需要一个参数 - 要测试的元素。

如何编写一个函数foo(const CMyClass &Bad),从列表中删除所有等于Bad的元素?

谢谢

PS

struct CMyClass {
    void *Ptr;
    int Var;
}

bool is_equal(const CMyClass &A, const CMyClass &B)
{
    if (A.Ptr == B.Prt and A.Var == B.Var)
        return true;
    else
        return false;
}

【问题讨论】:

  • 请添加 CMyClass 示例定义和匹配条件。
  • 我认为主要问题是您无法提交可用于比较的附加数据参数。我不知道函数对象是否可以在这里提供帮助(从未使用过它们)。

标签: c++ list stl


【解决方案1】:

如果条件匹配,您可以简单地遍历元素,比较和擦除,例如:

for (std::list<string>::iterator i = mylist.begin(), e = mylist.end(); i != e; )
{
    if (*i == "foobar")
       i = mylist.erase(i);
    else
       ++i;
}

【讨论】:

    【解决方案2】:

    你的班级必须在你的班级名称中实现 operator ==

    bool operator == ( const Class& rhs );
    

    然后你就可以使用了

    list.remove( Bad )
    

    如果你的班级有 operator == (不仅仅是 remove )是合理的 - 那么 list::remove 对你的解决方案有好处。 if operator == only for list::remove 比使用 remove_if 更好。

    在下面的示例中 list::remove 和 list::remove_if 被演示。

    struct Class
    {
        int a_;
        int b_;
    
        Class( int a, int b ):
            a_( a ),
            b_( b )
        {}
    
        bool operator == (const Class &rhs)
        {
            return (rhs.a_ == a_ && rhs.b_ == b_);
        }
    
        void print()
        {
            std::cout << a_ << " " << b_ << std::endl;
        }
    };
    
    bool isEqual( Class lhs, Class rhs )
    {
        return (rhs.a_ == lhs.a_ && rhs.b_ == lhs.b_);
    }
    
    struct IsEqual
    {
        IsEqual( const Class& value ):
            value_( value )
        {}
    
        bool operator() (const Class &rhs)
        {
            return (rhs.a_ == value_.a_ && rhs.b_ == value_.b_);
        }
    
        Class value_;
    };
    
    int main()
    {
        std::list<Class> l;
    
        l.push_back( Class( 1, 3 ) );
        l.push_back( Class( 2, 5 ) );
        l.push_back( Class( 3, 5 ) );
        l.push_back( Class( 3, 8 ) );
    
        Class bad( 2, 5 );
    
        std::cout << "operator == " << std::endl;
        l.remove( bad );
        std::for_each( l.begin(), l.end(), std::mem_fun_ref( &Class::print ) );
    
        std::cout << "binary function predicat" << std::endl;
        l.push_back( Class( 2, 5 ) );
        l.remove_if( std::bind2nd( std::ptr_fun(isEqual), bad ) );
        std::for_each( l.begin(), l.end(), std::mem_fun_ref( &Class::print ) );
    
    
        std::cout << "functor predicat" << std::endl;
        l.push_back( Class( 2, 5 ) );
        l.remove_if( IsEqual( bad ) );
        std::for_each( l.begin(), l.end(), std::mem_fun_ref( &Class::print ) );
    
        return 0;
    }
    

    【讨论】:

    • remove 如何知道比较两个 CMyClass 对象?
    • 它使用 ==-operator(你可以在你的类中覆盖它)
    • 您想要没有运算符 == 的解决方案吗?那么请告诉我们您想如何比较值或给我们一个可以做到这一点的函数名称?
    • std::list::remove 成员函数优于 std::remove + std::list::erase。
    • @dalle:谢谢。我很少使用列表,以至于我总是忘记这一点。
    【解决方案3】:
    using namespace std;
    
    class Foo
    {
        public:
            Foo(int newVal){value = newVal;}
            int value;
    };
    
    class checkEqual : public binary_function<Foo, Foo, bool>
    {
        public:
            bool operator()(const Foo &inputOne, const Foo &inputTwo) const
            {   return inputOne.value == inputTwo.value;}
                // implement your comparison here
    };
    
    int main(int count, char** args)
    {
        list<Foo> myList;
    
        for(int x = 0; x < 10; ++x)
            myList.push_back(Foo(x));
    
        Foo bad(5);
    
        myList.remove_if(bind2nd(checkEqual(), bad));    
    
        return 0;
    }
    

    或者如果你想重载 == 你可以这样做:

    class Foo
    {
        public:
            Foo(int newVal){value = newVal;}
            int value;
            bool operator==(const Foo &other) const
                {    return this->value == other.value;}
                     // your comparison here
    };
    

    然后:

    myList.remove(bad);
    

    【讨论】:

      【解决方案4】:

      实现 operator==(const CMyClass &)。

      例如:

      #include <list>
      #include <iostream>
      #include <iterator>
      using namespace std;
      
      class CMyClass {
      public:
        CMyClass(const int d) : data(d) {}
        bool operator==(const CMyClass &rhs) { return data == rhs.data; }
      friend
        ostream& operator<<(ostream &ost, const CMyClass &rhs) { return ost << rhs.data; }
      private:
        int data;
      };
      
      
      int main(int, char **) {
        list<CMyClass> li;
        CMyClass a(1);
        CMyClass b(8);
        li.push_back(a);
        li.push_back(b);
        copy(li.begin(), li.end(), ostream_iterator<CMyClass>(cout,"\n"));
        li.remove(a);
        copy(li.begin(), li.end(), ostream_iterator<CMyClass>(cout,"\n"));
        return 0;
      }
      

      结果:

      1 8 8

      【讨论】:

        【解决方案5】:

        根据谓词删除所有元素:

        struct Pred
        {
           bool operator()(int i) const
           {
              return i == 42;
           }
        };
        
        std::list<int> l = ...;
        l.remove_if(Pred());
        

        或删除所有值为 42 的元素:

        std::list<int> l = ...;
        l.remove(42);
        

        或者对于 CMyClass 的列表:

        struct Pred
        {
           bool operator()(const CMyClass& item) const
           {
              return item.GetSomething() == 42 && item.GetSomethingElse() == 314159;
           }
        };
        
        std::list<CMyClass> l = ...;
        l.remove_if(Pred());
        

        【讨论】:

          【解决方案6】:

          创建一个接受错误值并将其存储在成员变量中的类。然后实现

          bool operator()(CMyClass const &currVal) { 
            return (currVal is equal to this->bad);
          }
          

          将此对象的一个​​实例传递给 remove_if

          【讨论】:

            【解决方案7】:

            尝试使用 remove_if 方法

            http://www.sgi.com/tech/stl/remove_if.html

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2018-04-19
              • 2018-06-14
              • 2016-08-16
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多