【问题标题】:How would you remove elements of a std::vector based on some property of the elements?您将如何根据元素的某些属性删除 std::vector 的元素?
【发布时间】:2009-03-14 07:42:46
【问题描述】:

如果你有一个std::vector<MyClass>,其中MyClass有一个公共方法:bool isTiredOfLife(),你如何删除返回true的元素?

【问题讨论】:

    标签: c++ algorithm stl vector


    【解决方案1】:

    我更喜欢 remove_if

    v.erase(remove_if(v.begin(), v.end(), 
                     mem_fun_ref(&MyClass::isTiredOfLife)), 
            v.end());
    

    remove_if 返回一个迭代器,指向仍在序列中的最后一个元素。 erase 擦除从第一个参数到最后一个参数(两个迭代器)的所有内容。

    【讨论】:

    • 我忘了 remove_if() +1。
    • 好吧,我们真的不需要擦除;我们使用,因为删除变体不会删除元素,只是将它们附加到末尾。
    【解决方案2】:

    使用 remove_if 是执行此操作的“正确”方式。注意不要使用迭代器来循环和擦除,因为删除项目会使迭代器失效。事实上,任何使用 erase() 作为其主要方法的示例在向量上都是一个坏主意,因为擦除是 O(n),这将使你的算法 O(n^2)。这应该是一个 O(n) 算法。

    我在下面给出的方法可能比 remove_if 更快,但与 remove_if 不同,它不会保留元素的相对顺序。如果您关心维护顺序(即您的向量已排序),请使用 remove_if,如上面的答案所示。如果您不关心顺序,并且要删除的项目数通常小于向量的四分之一,则此方法可能会更快:

    for( size_t i = 0; i < vec.size(); )
       if( vec[i].isTiredOfLife() )
       {
          vec[i] = vec.back();
          vec.pop_back();
       }
       else
          ++i;
    

    【讨论】:

    • 哦。我忘记了。它甚至在我链接的页面中以粗体显示。 :o 我已经删除了我的帖子,所以没有人使用它。
    • 这不会重新排列向量中的元素吗?假设,例如,输入向量已排序,输出向量不会,最后一个元素将占据第一个删除元素的位置。
    • 您可能想更新您的答案,不再参考伯纳德的答案。
    • 是的,这将重新排列向量中的元素。如果您不关心顺序,那很好(它可能比 remove_if 更快,尤其是在数据类型复杂的情况下),但如果您需要相对顺序保持不变,那就不好了。
    猜你喜欢
    • 2021-10-17
    • 2016-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-22
    • 1970-01-01
    相关资源
    最近更新 更多