如何从 stl 向量中删除具有特定值的项目?
我正在查看 stl 矢量的 API 文档,并注意到矢量类上没有允许删除具有特定值的元素的方法。 这似乎是一个常见的操作,并且没有内置的方法来执行此操作似乎很奇怪。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(12)
如果你想在没有任何额外内容的情况下做到这一点:
If you want to do it without any extra includes:
类似于擦除删除惯用语,用于
向量 可以使用
resize
和remove
并使用迭代器距离计算:经过测试 此处。
Similar to the erase remove idiom, for
vector
one could useresize
andremove
and use iterator distance computation:Tested here.
一个更短的解决方案(不会强迫您重复向量名称 4 次)是使用 Boost:
请参阅 http://www.boost.org/doc/libs/1_64_0/libs/range/doc/html/range/reference /algorithms/new/remove_erase.html
A shorter solution (which doesn't force you to repeat the vector name 4 times) would be to use Boost:
See http://www.boost.org/doc/libs/1_64_0/libs/range/doc/html/range/reference/algorithms/new/remove_erase.html
有两种方法可以用来专门删除某个项目。
让我们取一个向量
1)非有效的方式:虽然它看起来相当有效,但这并不是因为擦除函数删除了元素并将所有元素向左移动1。
因此其复杂度为 O(n^2)
2) 高效方法(推荐):也称为ERASE - REMOVE idioms em>。
它只是将不匹配的部分转移到起始位置,并为新的有效末端提供一个迭代器。
它只需要 O(n) 复杂度。
删除算法的输出是:
因为删除的返回类型是到该范围的新末尾的迭代器。
现在使用向量的擦除函数删除向量新端到旧端的元素。 需要 O(1) 时间。
所以这个方法的工作时间复杂度为 O(n)
Two ways are there by which you can use to erase an item particularly.
lets take a vector
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)
2) Efficient way ( RECOMMENDED ) : It is also known as ERASE - REMOVE idioms .
It just shifted the non matched to starting and gives an iterator to new valid end.
It just requires O(n) complexity.
output of the remove algorithm is :
as return type of remove is iterator to the new end of that range.
Now use vector’s erase function to delete elements from the new end to old end of the vector. It requires O(1) time.
so this method work in O(n)
*
*
C++ 20 现在提供了一种简单的方法。
它变得很简单:
您应该查看 std::erase和 std::erase_if。
它不仅会删除该值的所有元素(此处为“0”),而且会以 O(n) 时间复杂度完成此操作。 这是你能得到的最好的。
如果您的编译器不支持 C++ 20,则应使用 erase-remove idiom:
*
*
C++ 20 provides an easy way of doing it now.
It gets as simple as :
You should check out std::erase and std::erase_if.
Not only will it remove all elements of the value (here '0'), it will do it in O(n) time complexity. Which is the very best you can get.
If your compiler does not support C++ 20, you should use erase-remove idiom:
另请参阅 std::remove_if 以便能够使用谓词...
这是上面链接中的示例:
See also std::remove_if to be able to use a predicate...
Here's the example from the link above:
从c++20开始:
引入了非成员函数
std::erase
,它将要删除的向量和值作为输入。前任:
From c++20:
A non-member function introduced
std::erase
, which takes the vector and value to be removed as inputs.ex:
其他答案涵盖了如何做好这一点,但我想我还要指出,这不在向量 API 中并不奇怪:它是低效的,通过向量线性搜索值,然后是一堆复制以将其删除。
如果您密集地执行此操作,出于这个原因,可能值得考虑使用 std::set 。
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.
If you're doing this operation intensively, it can be worth considering std::set instead for this reason.
如果您有一个未排序的向量,那么您可以简单地与最后一个向量元素交换,然后
resize()
。对于有序容器,您最好使用
std::vector::erase()
。 请注意,
中定义了std::remove()
,但实际上并没有执行擦除操作。 (仔细阅读文档)。If you have an unsorted vector, then you can simply swap with the last vector element then
resize()
.With an ordered container, you'll be best off with
std::vector::erase()
. Note that there is astd::remove()
defined in<algorithm>
, but that doesn't actually do the erasing. (Read the documentation carefully).将全局方法 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
感谢 Jim Buck 指出我的错误。
Use the global method std::remove with the begin and end iterator, and then use std::vector.erase to actually remove the elements.
Documentation links
std::remove http://www.cppreference.com/cppalgorithm/remove.html
std::vector.erase http://www.cppreference.com/cppvector/erase.html
Thanks to Jim Buck for pointing out my error.
std::remove
实际上并不从容器中删除元素:它会覆盖容器开头不应删除的元素,并返回指向它们之后的下一个元素的迭代器。 可以将此迭代器传递给container_type::erase
以实际删除现在位于容器末尾的额外元素:std::remove
does not actually erase elements from the container: it overwrites the elements that should not be removed at the beginning of the container, and returns the iterator pointing to the next element after them. This iterator can be passed tocontainer_type::erase
to do the actual removal of the extra elements that are now at the end of the container:如果您想删除一个项目,下面的方法会更有效一些。
或者,如果顺序对您来说不重要,您可以避免移动项目的开销:
这就是 Jim 的
std::vector::erase
+std::remove
方法在幕后做的。If you want to remove an item, the following will be a bit more efficient.
or you may avoid overhead of moving the items if the order does not matter to you:
Which is what Jim's method of
std::vector::erase
+std::remove
does under the hood.