在列表中循环时删除数据

发布于 2025-02-05 18:51:05 字数 2529 浏览 1 评论 0原文

我很难弄清楚如何从列表中删除项目。

请注意,我想从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;
}

更新:我忘了陈述实际目标

我的目标是删除sct_osc_fill ordinfo s Advance() Method < /strong>(该部分很重要),然后离开其余部分。我的实际项目代码所做的超过显示的功能,这些函数名称仅在此示例中构成。.其中有更多代码与操纵列表没有直接相关(但与处理order> orderiNfo有关)在我的实际项目中。我的目标是在列表中留下 o1的一份,以及o2o4O6 - 删除o3o5,因为它们具有sct_osc_filld orderinfo.statuscode

I'm having trouble figuring out how to delete an item from a list.

Please note that I would like to perform the deletion from the advance() function. This code is just boiled down from my actual project, to try to isolate the error.

#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;
}

update: I forgot to state the actual goal

my goal is to just delete SCT_OSC_FILLED ordInfos from within the advance() method (that part is important) and leave the rest. My actual project code does more than what is shown, these names of functions are just made up for this example.. there is more code in them not directly related to manipulating the list (but related to processing OrderInfo) in my actual project. My goal is to leave one copy of o1 in the list as well as o2, o4 and o6 - removing o3 and o5 because they have an SCT_OSC_FILLED OrderInfo.statusCode

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

稳稳的幸福 2025-02-12 18:51:05

因此,问题与列表中的删除无关。考虑到既定目标,您的逻辑简直是错误的。

您想在添加项目时从列表中删除所有sct_osc_fill项目,但是当您添加sct_osc_filld的代码时,您编写的代码会从列表中删除所有项目。您只是在测试错误的事情。

一旦进行了更改

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++;
    }
}

So the problem is nothing to do with deletion from a list. Your logic is simply wrong given the stated goal.

You want to delete all SCT_OSC_FILLED items from the list when adding an item but the code you write deletes all items from the list when you add an item with SCT_OSC_FILLED. You are simply testing the wrong thing.

Change this

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++;
}

to this

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++;
}

Once you make that change you can see that the ordInfo parameter is unused. Add bit more cleanup and you end up with this much simpler function

void advance(std::list <OrderInfo> ::iterator& orderIter) {
    if (orderIter->statusCode == SCT_OSC_FILLED) {
        orderIter = MasterOrders.erase(orderIter);
    }
    else {
        orderIter++;
    }
}
喜你已久 2025-02-12 18:51:05

根据 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;
        }
    }

擦除将迭代器返回下一个元素(如果删除元素是最后一个元素,则end(end()),因此“ IT = c.erase(it);”使“ IT”指向下一个元素,并且不需要增加迭代器(使用++)。

因此,您可以拥有类似的东西:

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

According to cppreference.com, "References and iterators to the erased elements are invalidated." You should get an iterator to the next element, before deleting the current element.

In the same page, cppreference gives an example:

// 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 returns an iterator to the next element (end() if the removed element was the last), so "it = c.erase(it);" makes "it" to point to the next element, and there is no need for incrementing the iterator (with ++).

So you could have something like:

void advance(OrderInfo ordInfo, std::list <OrderInfo> ::iterator& orderIter) {
    if (ordInfo.statusCode == SCT_OSC_FILLED) {
        orderIter = MasterOrders.erase(orderIter);
    } else {
        orderIter++;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文