在遍历列表时删除数据



我不知道如何从列表中删除一个项目。

请注意,我想从advance()函数中执行删除。这段代码只是从我的实际项目中提炼出来的,试图隔离错误。

#include <iostream>
#include <list>
#include <iterator>
#include <algorithm>
using namespace std;
const int SCT_OSC_FILLED = 11;
class OrderInfo {
private: 
std::string id;
public:
OrderInfo(std::string a, int aStatusCode);
std::string key();
int statusCode;
};
OrderInfo::OrderInfo(std::string a, int aStatusCode) {
id = a;
statusCode = aStatusCode;
}
std::string OrderInfo::key() {
return id;
}
std::list <OrderInfo> MasterOrders;
void testList();
void add(OrderInfo ordInfo);
void advance(OrderInfo ordInfo, std::list <OrderInfo> ::iterator& orderIter);
void testList() {
OrderInfo o1("1", 15);
OrderInfo o2("2", 16);
OrderInfo o3("3", SCT_OSC_FILLED);
OrderInfo o4("4", 17);
OrderInfo o5("5", SCT_OSC_FILLED);
OrderInfo o6("6", 18);
add(o1);
add(o1);
add(o2);
add(o3);
add(o4);
add(o5);
add(o6);
for (auto v : MasterOrders)
std::cout << v.key() << "n";
}
void add(OrderInfo ordInfo) {
// Add to MasterOrders (if not already in list)
bool alreadyInList = false;
std::list <OrderInfo> ::iterator orderIter = MasterOrders.begin();
while (orderIter != MasterOrders.end())
{
OrderInfo oi = *orderIter;
alreadyInList = ordInfo.key() == oi.key(); 
if (alreadyInList) break;
advance(ordInfo, orderIter);
}
if (!alreadyInList) MasterOrders.push_front(ordInfo);
}
void advance(OrderInfo ordInfo, std::list <OrderInfo> ::iterator& orderIter) {
bool iterate = true;
if (ordInfo.statusCode == SCT_OSC_FILLED) {
orderIter = MasterOrders.erase(orderIter++); // https://stackoverflow.com/a/5265561/270143
iterate = false;
}   

if (iterate) orderIter++;
}
int main()
{
testList();
return 0;
}

更新:我忘了说明实际的目标

我的目标是从advance()方法中删除SCT_OSC_FILLEDordInfos(那部分很重要),剩下的就别管了。我实际的项目代码所做的比所显示的要多,这些函数的名称只是为了这个例子而组成的。在我的实际项目中,有更多的代码与操纵列表没有直接关系(但与处理OrderInfo有关)。我的目标是在列表中留下o1一个副本以及o2,o4o6-删除o3o5,因为它们有SCT_OSC_FILLEDOrderInfo.statusCode

所以这个问题与从列表中删除无关。考虑到既定的目标,你的逻辑完全是错误的。

您想在添加项目时从列表中删除所有SCT_OSC_FILLED项,但是您编写的代码在添加具有SCT_OSC_FILLED的项目时从列表中删除了所有项目。你只是在测试错误的东西。

改变这

void advance(OrderInfo ordInfo, std::list <OrderInfo> ::iterator& orderIter) {
bool iterate = true;
if (ordInfo.statusCode == SCT_OSC_FILLED) {
orderIter = MasterOrders.erase(orderIter++);
iterate = false;
}   

if (iterate) orderIter++;
}

void advance(OrderInfo ordInfo, std::list <OrderInfo> ::iterator& orderIter) {
bool iterate = true;
if (orderIter->statusCode == SCT_OSC_FILLED) {
orderIter = MasterOrders.erase(orderIter);
iterate = false;
}   

if (iterate) orderIter++;
}

一旦您进行了更改,您可以看到ordInfo参数未使用。添加更多的清理,最终得到这个简单得多的函数

void advance(std::list <OrderInfo> ::iterator& orderIter) {
if (orderIter->statusCode == SCT_OSC_FILLED) {
orderIter = MasterOrders.erase(orderIter);
}
else {
orderIter++;
}
}

根据cppreference.com,对已删除元素的引用和迭代器无效。在删除当前元素之前,应该先获取到下一个元素的迭代器。

在同一个页面中,cppreference给出了一个例子:

// Erase all even numbers (C++11 and later)
for (std::list<int>::iterator it = c.begin(); it != c.end(); ) {
if (*it % 2 == 0) {
it = c.erase(it);
} else {
++it;
}
}

erase返回指向下一个元素的迭代器(如果被删除的元素是最后一个元素,则为end()),因此"it = c.erase(it);"让"你;指向下一个元素,不需要对迭代器进行自增操作(使用++)。

你可以这样写:

void advance(OrderInfo ordInfo, std::list <OrderInfo> ::iterator& orderIter) {
if (ordInfo.statusCode == SCT_OSC_FILLED) {
orderIter = MasterOrders.erase(orderIter);
} else {
orderIter++;
}
}

最新更新