C++ 从向量中删除项目的有效方法
目前,我计划从vector中删除所有项,这在集合中找不到 例如: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");
#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());