Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/134.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 从向量中删除项目的有效方法_C++ - Fatal编程技术网

C++ 从向量中删除项目的有效方法

C++ 从向量中删除项目的有效方法,c++,C++,目前,我计划从vector中删除所有项,这在集合中找不到 例如: #include <vector> #include <set> #include <string> #include <iostream> using namespace std; int main() { std::set<string> erase_if_not_found; erase_if_not_found.insert("a");

目前,我计划从vector中删除所有项,这在集合中找不到

例如:

#include <vector>
#include <set>
#include <string>
#include <iostream>

using namespace std;

int main() {
    std::set<string> erase_if_not_found;
    erase_if_not_found.insert("a");
    erase_if_not_found.insert("b");
    erase_if_not_found.insert("c");

    std::vector<string> orders;
    orders.push_back("a");
    orders.push_back("A");
    orders.push_back("A");
    orders.push_back("b");
    orders.push_back("c");
    orders.push_back("D");

    // Expect all "A" and "D" to be removed.
    for (std::vector<std::string>::iterator itr = orders.begin(); itr != orders.end();) {
        if (erase_if_not_found.find(*itr) == erase_if_not_found.end()) {
            orders.erase(itr);
            // Begin from start point again? Do we have a better way?
            itr = orders.begin();
        } else {
            ++itr;
        }
    }

    for (std::vector<std::string>::iterator itr = orders.begin(); itr != orders.end(); ++itr) {
        std::cout << *itr << std::endl;
    }

    getchar();
}
#包括
#包括
#包括
#包括
使用名称空间std;
int main(){
std::如果未找到,则设置擦除;
如果未找到,则删除。插入(“a”);
如果未找到,则删除。插入(“b”);
如果未找到,则删除。插入(“c”);
向量序;
订单。推回(“a”);
订单。推回(“A”);
订单。推回(“A”);
订单。推回(“b”);
命令。推回(“c”);
命令。推回(“D”);
//希望删除所有“A”和“D”。
for(std::vector::iterator itr=orders.begin();itr!=orders.end();){
if(如果未找到则擦除。查找(*itr)=如果未找到则擦除。结束(){
命令。擦除(itr);
//重新从起点开始?我们有更好的方法吗?
itr=orders.begin();
}否则{
++itr;
}
}
for(std::vector::iterator itr=orders.begin();itr!=orders.end();++itr){

std::cout是的,有一个更好的方法-您可以在向量末尾移动要删除的项。然后在循环结束后剪切向量的结尾。

我建议复制要保留在另一个向量中的元素,而不是在每次删除后从开始再次解析向量。
此外,如果集合在循环中不再被修改,那么您应该将
end()
方法返回的迭代器存储在循环外,因为调用
end()
对于某些STL实现来说代价很高。一些编译器正在对此进行优化,但并不总是如此。

它可能有助于首先对向量进行排序,因为集合本身是有序的。
一种变体可能是按集合中的存在对向量排序,然后立即切掉所有项。

是;您可以将擦除/删除习惯用法与自定义谓词一起使用:

template <typename SetT>
struct not_contained_in_set_impl
{
    not_contained_in_set_impl(const SetT& s) : set_(s) { }

    template <typename T>
    bool operator()(const T& v)
    {
        return set_.find(v) == set_.end();
    }

    const SetT& set_;
};

template <typename SetT>
not_contained_in_set_impl<SetT> not_contained_in_set(const SetT& s)
{
    return not_contained_in_set_impl<SetT>(s);
}
[在我脑海中快速编译]


如果您愿意首先对范围进行排序,您还有其他可能表现更好的选项(
std::set_intersection

我不确定您要求的是两个向量的交集,但如果是,您可以看一看

但它需要排序向量。

算法remove_if()可以做到这一点,但您需要一个谓词来确定该项是否不在您的集合中

还可以使用remove\u copy\u if()将项目复制到新向量中


如果对向量进行了排序,则可以使用set_intersection。这也将只允许找到每个元素的一个副本。

如果修改向量,即使在最后修改,是否可以保证迭代器循环仍然有效?如果仅通过交换两个项来修改向量,迭代器将不会无效。添加可能会使其无效。缓存end()在这里不是一个好主意,因为调用erase()时它将无效。我建议不要再调用erase(),这样在这种情况下end()就可以缓存了。[在我脑子里动态编译]啊,那个优化器怎么样了?我认为在集合impl中未包含的构造函数命名是错误的。而且,它应该是orders.erase而不是std::erase。但这是一个很好的解决方案。@Roger:我不太担心优化器:正如@Yan指出的,我的解析器需要一些工作,特别是在凌晨2点。:-,尽管有“remove\u if”代码中,您可以始终使用整数索引向后迭代向量。您可以自由删除一个元素,然后移动到前一个元素而不会出现问题。我经常这样做。
orders.erase(
    std::remove_if(orders.begin(),
                   orders.end(),
                   not_contained_in_set(erase_if_not_found)), 
    orders.end());