我正在查看STL vector的API文档,注意到vector类中没有允许移除某个特定值元素的方法。这似乎是一种常见操作,也很奇怪为什么没有内置方法可以实现这个功能。
我正在查看STL vector的API文档,注意到vector类中没有允许移除某个特定值元素的方法。这似乎是一种常见操作,也很奇怪为什么没有内置方法可以实现这个功能。
std::remove
并不实际从容器中删除元素:它会覆盖容器开头不应被删除的元素,并返回指向它们之后下一个元素的迭代器。这个迭代器可以传递给container_type::erase
来实际删除现在位于容器末尾的额外元素。std::vector<int> vec;
// .. put in some values ..
int int_to_remove = n;
vec.erase(std::remove(vec.begin(), vec.end(), int_to_remove), vec.end());
vec.end()
在调用std::remove
之前和之后保证是相同的?从我阅读网上其他部分的内容来看,这看起来是安全的,但应明确说明。 - dmckee --- ex-moderator kittenvec.end()
不需要相同,但没关系,因为std::remove
不会改变它。如果它改变了它(并使旧值无效),那么会有问题:参数的求值顺序是未指定的,因此您不知道第二个vec.end()
在使用时是否仍然有效。其相同的原因很简单,std::remove
不会改变容器的大小,它只是移动内容。 - Steve Jessopconst char *_Filename
的 std::remove()
函数。我需要调用哪个方法呢? - Victorremove
版本。为了访问用于处理容器的remove
版本,您需要包含<algorithm>
。 - Jim Buckstd::vector<int> v;
auto it = std::find(v.begin(), v.end(), 5);
if(it != v.end())
v.erase(it);
或者如果对您来说顺序不重要,您可以避免移动物品的开销:
std::vector<int> v;
auto it = std::find(v.begin(), v.end(), 5);
if (it != v.end()) {
using std::swap;
// swap the one to be removed with the last element
// and remove the item at the end of the container
// to prevent moving all items after '5' by one
swap(*it, v.back());
v.pop_back();
}
这就是Jim的方法std::vector::erase
+std::remove
在底层执行的操作。
std::vector<int> v;
v.push_back(1);
v.push_back(2);
//Vector should contain the elements 1, 2
//Find new end iterator
std::vector<int>::iterator newEnd = std::remove(v.begin(), v.end(), 1);
//Erase the "removed" elements.
v.erase(newEnd, v.end());
//Vector should now only contain 2
来自 c++20:
引入了一个非成员函数std::erase
,它接受向量和要删除的值作为输入。
例如:
std::vector<int> v = {90,80,70,60,50};
std::erase(v,50);
map::erase
! - L. F.另请参阅std::remove_if,以便使用谓词...
这是上面链接中的示例:
vector<int> V;
V.push_back(1);
V.push_back(4);
V.push_back(2);
V.push_back(8);
V.push_back(5);
V.push_back(7);
copy(V.begin(), V.end(), ostream_iterator<int>(cout, " "));
// The output is "1 4 2 8 5 7"
vector<int>::iterator new_end =
remove_if(V.begin(), V.end(),
compose1(bind2nd(equal_to<int>(), 0),
bind2nd(modulus<int>(), 2)));
V.erase(new_end, V.end()); [1]
copy(V.begin(), V.end(), ostream_iterator<int>(cout, " "));
// The output is "1 5 7".
resize()
。std::vector::erase()
。请注意,在<algorithm>
中定义了std::remove()
,但它实际上并没有执行删除操作。(请仔细阅读文档)。*
C++社区听到了你的请求 :)*
C++ 20现在提供了一种简单的方法。 它变得如此简单:
#include <vector>
...
vector<int> cnt{5, 0, 2, 8, 0, 7};
std::erase(cnt, 0);
您应该查看std::erase和std::erase_if。
它不仅可以删除所有值(这里是“0”)的元素,而且还可以在O(n)时间复杂度下完成。这是您可以获得的最佳效果。
如果您的编译器不支持C++ 20,则应使用erase-remove idiom:
#include <algorithm>
...
vec.erase(std::remove(vec.begin(), vec.end(), 0), vec.end());
#include <boost/range/algorithm_ext/erase.hpp>
// ...
boost::remove_erase(vec, int_to_remove);
有两种方法可以用来特别删除一个项目。让我们以向量为例。
std :: vector < int > v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
v.push_back(40);
v.push_back(40);
v.push_back(50);
1)非高效方法:尽管它看起来相当高效,但实际上并不是,因为 erase 函数会删除元素,并将所有元素向左移动 1 个位置。 因此,它的复杂度为 O(n^2)
std :: vector < int > :: iterator itr = v.begin();
int value = 40;
while ( itr != v.end() )
{
if(*itr == value)
{
v.erase(itr);
}
else
++itr;
}
2) 高效的方法(推荐):也被称为ERASE-REMOVE习语。
remove算法的输出是:
10 20 30 50 40 50
由于remove的返回类型是指向该范围新结尾的迭代器,因此需要注意。
template <class ForwardIterator, class T>
ForwardIterator remove (ForwardIterator first, ForwardIterator last, const T& val);
v.erase ( std :: remove (v.begin() , v.end() , element ) , v.end () );
所以这个方法的时间复杂度是O(n)