我正在查看stl向量的API文档,并注意到vector类上没有允许删除具有特定值的元素的方法。这似乎是一种常见的操作,看起来很奇怪,没有内置的方法可以做到这一点。
答案 0 :(得分:151)
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());
答案 1 :(得分:57)
如果您要删除 项,以下内容会更有效。
std::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();
}
答案 2 :(得分:15)
将global方法std :: remove与begin和end迭代器一起使用,然后使用std :: vector.erase实际删除元素。
文档链接
std :: remove http://www.cppreference.com/cppalgorithm/remove.html
std :: vector.erase http://www.cppreference.com/cppvector/erase.html
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
感谢Jim Buck指出我的错误。
答案 3 :(得分:5)
如果你有一个未排序的向量,那么你可以简单地用最后一个向量元素交换resize()
。
使用已订购的容器,您最好使用std::vector::erase()
。请注意,std::remove()
中定义了<algorithm>
,但实际上并没有进行删除。 (仔细阅读文档)。
答案 4 :(得分:5)
其他答案涵盖了如何很好地做到这一点,但我想我也会指出,这不是在矢量API中并不奇怪:它是低效的,线性搜索值的向量,其次通过一堆复制来删除它。
如果您正在密集地执行此操作,则可能因此考虑使用std :: set。
答案 5 :(得分:3)
更短的解决方案(不会强迫你重复4次矢量名称)将使用Boost:
#include <boost/range/algorithm_ext/erase.hpp>
// ...
boost::remove_erase(vec, int_to_remove);
答案 6 :(得分:2)
另请参阅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".
答案 7 :(得分:1)
来自 c ++ 20 :
引入了一个非成员函数name
,该函数将要删除的向量和值作为输入。
例如:
std::erase
答案 8 :(得分:1)
*
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());
答案 9 :(得分:0)
如果你想在没有任何额外包含的情况下这样做:
device_id
答案 10 :(得分:0)
有两种方法可以用来擦除项目。 让我们取一个向量
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)非有效方式:尽管它似乎很有效,但这不是因为擦除功能会删除元素并将所有元素向左移动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习惯用法 。
删除算法的输出是:
10 20 30 50 40 50
remove的返回类型是迭代器到该范围的新末端。
template <class ForwardIterator, class T>
ForwardIterator remove (ForwardIterator first, ForwardIterator last, const T& val);
现在使用矢量的擦除功能从矢量的新端到旧端删除元素。这需要O(1)时间。
v.erase ( std :: remove (v.begin() , v.end() , element ) , v.end () );
因此该方法适用于O(n)