std:vector的替代项,用于在遍历循环时删除其元素
Alternative for std:vector to remove its elements while going through a loop?
我的循环遍历向量的元素。在这个循环中,一些元素正在被删除(我希望它们被删除)。虽然std::vector不允许这样做,但我想要一个替代方案。
for(unsigned int j = 0; j < rectArray.size(); j++)
{
if( rectArray[j] == 2 )
{
rectArray.erase(rectArray.begin() + j);
}
//...
}
你认为std::列表在这里会好吗?我能用点别的吗?
除非向量的元素复制成本很高,否则最简单的方法可能是将std::copy_if
(或以其他方式复制您想要保留的元素)复制到一个新向量中,然后与原始向量交换。还有remove_if
和resize
。
如果元素的重新定位非常昂贵,那么list
可以避免这种情况,但这取决于您对集合的其他操作。如果你用list
做了其他非常慢的事情,那么你就把问题转移到了其他地方。
我建议修改您的代码,使其使用迭代器而不是实际的向量。它像这样更清洁、更高效:
for (auto it = rectArray.begin(); it != rectArray.end(); ++it)
{
// Access the current element with *it
// If you want you can pass `it` and `rectArray.end()` as
// the lower and upper bounds of the new collection,
// rather than doing expensive resizes of the vector.
}
注意,auto
是一个C++11特性(我使用它的方式)。如果您的编译器支持,您可能还想使用C++11的foreach:
for (auto it : rectArray) {
// same as before
}
从向量中间删除一个元素是非常昂贵的,因为您必须向下移动所有后面的元素。
如果您需要在容器的中间添加/删除元素,那么列表通常会更好。
列表比向量更好,因为从列表中间删除元素不会花费任何费用。另一方面,从向量中间移除元素具有线性复杂性。
std::remove_if
的可能替代品。速度快一点,不需要函子,但它不维持秩序。
auto end = std::end(rectArray);
for(auto it = std::begin(rectArray); it != end; ++it)
{
if(it->remove_me()))
std::swap(*it, *--end); // or even faster *it = std::move(*--end);
}
rectArray.erase(end, std::end(rectArray));
如果您正在进行大量删除,那么列表可能是最佳选择。下面是一些示例代码。
#include <vector>
#include <list>
#include <algorithm>
using namespace std;
class Widget
{
public:
explicit Widget(int someNumber);
bool ShouldDelete();
bool ShouldDeleteComplex(int a, int b, int c);
private:
int _someNumber;
};
Widget::Widget(int someNumber) : _someNumber(someNumber)
{
}
bool Widget::ShouldDelete()
{
if (_someNumber > 2)
{
return true;
}
return false;
}
bool Widget::ShouldDeleteComplex(int a, int b, int c)
{
if ((a * b - c) > _someNumber)
{
return true;
}
return false;
}
int main()
{
list<Widget> lw;
lw.push_back(Widget(1));
lw.push_back(Widget(2));
lw.push_back(Widget(3));
// delete from list using functor
lw.remove_if(mem_fun_ref(&Widget::ShouldDelete));
// delete from list using lambda function
lw.remove_if([] (Widget& x) { return x.ShouldDeleteComplex(1, 2, 0); } );
vector<Widget> vw;
vw.push_back(Widget(1));
vw.push_back(Widget(2));
vw.push_back(Widget(3));
// delete using functor
vw.erase(remove_if(vw.begin(), vw.end(), mem_fun_ref(&Widget::ShouldDelete)), vw.end());
// delete using lambda function
vw.erase(
remove_if(vw.begin(), vw.end(),
[] (Widget& x) { return x.ShouldDeleteComplex(1, 2, 0); }
),
vw.end());
return 0;
}
相关文章:
- 为什么即使使用 for 循环遍历我的向量,它也没有输出到控制台?(C++)
- 循环遍历标准的正确方法::array<char*, N>
- 我该如何循环遍历我的数组(缓冲区——包含一个文本文件),并将其打印成30字节的块
- 如何在重复循环中循环遍历 std::vector
- 数组 - 循环遍历辅助阵列
- 在C++中循环遍历二维数组时改进 O(n)
- 如何在 uwp c# 中循环遍历和检查 Xbox 控制器状态
- 循环遍历向量<string>并保持每个元素"count"时出现问题
- IOS objective-C 循环遍历 2 个数组
- 循环遍历地图时编译错误
- 在C 中的字符串向量的字符串元素中循环遍历所有字符
- 如何使用单 for 循环遍历 std::map<string>int 和 std::vector<int>?
- 循环遍历向量中的所有(无序)元素对
- 使用循环遍历三角形内的所有点
- 循环遍历CreateProcess输出的每一行
- 如何在指针表示法和数组表示法中循环遍历二维数组
- 使用 'for' 循环遍历C++向量
- 链表的循环遍历
- 在C++中循环遍历一个3d索引的1d数组
- 在循环遍历矢量时将对象添加到矢量