C++ 如何从具有特定值的 stl 向量中删除项目?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/39912/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I remove an item from a stl vector with a certain value?
提问by bradtgmurray
I was looking at the API documentation for stl vector, and noticed there was no method on the vector class that allowed the removal of an element with a certain value. This seems like a common operation, and it seems odd that there's no built in way to do this.
我正在查看 stl vector 的 API 文档,并注意到 vector 类上没有允许删除具有特定值的元素的方法。这似乎是一个常见的操作,而且没有内置的方法来执行此操作似乎很奇怪。
回答by Jim Buck
std::remove
does not actually erase the element from the container, but it does return the new end iterator which can be passed to container_type::erase
to do the REAL removal of the extra elements that are now at the end of the container:
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());
回答by Etherealone
If you want to remove anitem, the following will be a bit more efficient.
如果你想删除一个项目,下面的方法会更有效率一些。
std::vector<int> v;
auto it = std::find(v.begin(), v.end(), 5);
if(it != v.end())
v.erase(it);
or you may avoid overhead of moving the items if the order does not matter to you:
或者,如果订单对您无关紧要,您可以避免移动物品的开销:
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();
}
回答by bradtgmurray
Use the global method std::remove with the begin and end iterator, and then use std::vector.erase to actually remove the elements.
将全局方法 std::remove 与开始和结束迭代器一起使用,然后使用 std::vector.erase 实际删除元素。
Documentation links
std::remove http://www.cppreference.com/cppalgorithm/remove.html
std::vector.erase http://www.cppreference.com/cppvector/erase.html
文档链接
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
Thanks to Jim Buck for pointing out my error.
感谢 Jim Buck 指出我的错误。
回答by nsanders
If you have an unsorted vector, then you can simply swap with the last vector element then resize()
.
如果您有一个未排序的向量,那么您可以简单地与最后一个向量元素 then 交换resize()
。
With an ordered container, you'll be best off with ?std::vector::erase()
. Note that there is a std::remove()
defined in <algorithm>
, but that doesn't actually do the erasing. (Read the documentation carefully).
使用订购的容器,您最好使用 ? std::vector::erase()
. 请注意,在 中有一个std::remove()
定义<algorithm>
,但实际上并没有进行擦除。(仔细阅读文档)。
回答by Luke Halliwell
The other answers cover how to do this well, but I thought I'd also point out that it's not really odd that this isn't in the vector API: it's inefficient, linear search through the vector for the value, followed by a bunch of copying to remove it.
其他答案涵盖了如何做好这件事,但我想我还指出,这不在向量 API 中并不奇怪:它效率低下,线性搜索向量中的值,然后是一堆复制删除它。
If you're doing this operation intensively, it can be worth considering std::set instead for this reason.
如果您正在密集地执行此操作,那么出于这个原因考虑使用 std::set 是值得的。
回答by jhasse
A shorter solution (which doesn't force you to repeat the vector name 4 times) would be to use Boost:
更短的解决方案(不强制您重复向量名称 4 次)是使用 Boost:
#include <boost/range/algorithm_ext/erase.hpp>
// ...
boost::remove_erase(vec, int_to_remove);
回答by Pavan Chandaka
From c++20:
从C++20:
A non-member function introduced std::erase
, which takes the vector and value to be removed as inputs.
引入了一个非成员函数std::erase
,它将要删除的向量和值作为输入。
ex:
前任:
std::vector<int> v = {90,80,70,60,50};
std::erase(v,50);
回答by Xavier Nodet
See also std::remove_ifto be able to use a predicate...
另请参阅std::remove_if以能够使用谓词...
Here's the example from the link above:
这是上面链接中的示例:
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".
回答by Katianie
If you want to do it without any extra includes:
如果你想在没有任何额外包括的情况下做到这一点:
vector<IComponent*> myComponents; //assume it has items in it already.
void RemoveComponent(IComponent* componentToRemove)
{
IComponent* juggler;
if (componentToRemove != NULL)
{
for (int currComponentIndex = 0; currComponentIndex < myComponents.size(); currComponentIndex++)
{
if (componentToRemove == myComponents[currComponentIndex])
{
//Since we don't care about order, swap with the last element, then delete it.
juggler = myComponents[currComponentIndex];
myComponents[currComponentIndex] = myComponents[myComponents.size() - 1];
myComponents[myComponents.size() - 1] = juggler;
//Remove it from memory and let the vector know too.
myComponents.pop_back();
delete juggler;
}
}
}
}
回答by Praveen Kumar
Two ways are there by which you can use to erase an item particularly. lets take a vector
有两种方法可以用来特别擦除一个项目。让我们取一个向量
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) Non efficient way :Although it seems to be quite efficient but it's not because erase function delets the elements and shifts all the elements towards left by 1. so its complexity will be O(n^2)
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) Efficient way ( RECOMMENDED ): It is also known as ERASE - REMOVE idioms.
2)高效方式(推荐):它也被称为ERASE-REMOVE成语。
- std::remove transforms the given range into a range with all the elements that compare not equal to given element shifted to the start of the container.
- So, actually don't remove the matched elements. It just shifted the non matched to starting and gives an iterator to new valid end. It just requires O(n) complexity.
- std::remove 将给定范围转换为一个范围,其中所有比较不等于给定元素的元素都移动到容器的开头。
- 所以,实际上不要删除匹配的元素。它只是将不匹配的转移到开始,并为新的有效结束提供迭代器。它只需要 O(n) 复杂度。
output of the remove algorithm is :
删除算法的输出是:
10 20 30 50 40 50
as return type of remove is iterator to the new end of that range.
因为 remove 的返回类型是该范围新结束的迭代器。
template <class ForwardIterator, class T>
ForwardIterator remove (ForwardIterator first, ForwardIterator last, const T& val);
Now use vector's erase function to delete elements from the new end to old end of the vector. It requires O(1) time.
现在使用向量的擦除功能从向量的新端到旧端删除元素。它需要 O(1) 时间。
v.erase ( std :: remove (v.begin() , v.end() , element ) , v.end () );
so this method work in O(n)
所以这个方法在 O(n) 中工作