首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在列表语法中使用deletion更正迭代

在列表语法中使用deletion更正迭代
EN

Stack Overflow用户
提问于 2013-05-01 19:00:49
回答 3查看 204关注 0票数 1

我目前正在编写一个程序,它在程序中的某一点使用列表,我想迭代三个列表a,b和c,如果b和c中的任何元素出现在a中,则将其删除。我这样做:

代码语言:javascript
复制
//remove elements from OpenList that are in ClosedList
    for(list<Node> :: iterator cloIt = ClosedList.begin(); cloIt != ClosedList.end(); cloIt++)
    {
        for(list<Node> :: iterator opIt = OpenList.begin(); opIt != OpenList.end(); opIt++)
        {
            for(list<Node> :: iterator neigIt = Neighbour.begin(); neigIt != Neighbour.end(); neigIt++)
            {
                if (*cloIt == *opIt)
                {
                    opIt = OpenList.erase(opIt);

                }
                if (*cloIt == *neigIt)
                {
                    neigIt = Neighbour.erase(neigIt);
                }
            }
        }
    }

然而,这会导致我得到一个“列表迭代器不可递增”的错误,我该如何解决这个问题呢?

EN

回答 3

Stack Overflow用户

发布于 2013-05-01 19:25:17

从你的删除呼叫中,你想要

  1. remove OpenList items if ClosedList list

remove Neighbour items if from listremove Neighbour items如果在ClosedListlist中找到相邻项,则删除相邻项

你最好将代码分成两个循环,而不是嵌套循环,例如:

1.如果在ClosedList list中找到OpenList项,则将其删除

代码语言:javascript
复制
for(auto cloIt = ClosedList.begin(); cloIt != ClosedList.end(); ++cloIt)
{
   OpenList.remove_if([&](const Node& n){ return n == *colIt; } );
}

2.如果从ClosedListlist中找到相邻项目,则将其移除

代码语言:javascript
复制
for(auto cloIt = ClosedList.begin(); cloIt != ClosedList.end(); ++cloIt)
{
   Neighbour.remove_if([&](const Node& n){ return n == *colIt; } );
}

很明显,前面的代码是重复的,你可以为此编写一个通用函数:

代码语言:javascript
复制
void RemoveItem(std::list<Node>& node_list, std::list<Node>& node_list2)
{
   for(auto cloIt = node_list2.begin(); cloIt != node_list2.end(); ++cloIt)
   {
      node_list.remove_if([&](const Node& n){ return n == *colIt; } );
   }
}

现在你可以调用:

代码语言:javascript
复制
RemoveItem(OpenList, CloseList);
RemoveItem(Neighbour, CloseList);

更新:不要忘记为节点类型定义operator==,例如,如果节点有getId接口:

代码语言:javascript
复制
bool operator==(const Node& lhs, const Node& rhs)
{
  return lhs.getId() == rhs.getId();
}
票数 1
EN

Stack Overflow用户

发布于 2013-05-01 19:05:54

我该怎么解决这个问题呢?

最好的方法是使用标准算法,并让它们为您执行迭代、搜索和/或条件删除。

您可以将std::listremove_if()成员函数与检查元素是否包含在列表a中的lambda谓词一起使用

代码语言:javascript
复制
#include <algorithm>

// ...

b.remove_if(
    [&a] (Node const& n)
    {
        return (std::find(begin(a), end(a), n) != a.end());
    });

如果元素包含在a中,则与从c中删除元素相同。

另一种可能性是使用std::for_each()遍历a的所有元素,并从bc中删除它们

代码语言:javascript
复制
#include <algorithm>

// ...

std::for_each(begin(a), end(a),
    [&b, &c] (Node const& n)
    {
        b.remove(n);
        c.remove(n);
    });
票数 0
EN

Stack Overflow用户

发布于 2013-05-01 19:30:35

您已经正确地使用了.erase的返回值来获得新的迭代器,但是忘记了此迭代器在循环的当前迭代结束时立即获得++'d;如果.erase的结果为.end,则这是一个无效操作。

(实际上非常幸运的是,您在尝试递增现在无效的迭代器时得到了诊断结果-标准对这种情况没有任何保证。)

当你没有++ .erase**.**时,你只需要++就可以了

一般的模式如下所示:

代码语言:javascript
复制
for (typename list<T>::iterator it = l.begin(), end = l.end(); it != end; )
{
    // ^^ NB. no "it++" in the loop introduction!

    if (foo(*it)) {
       // condition satisfied; do the erase, and get the next
       // iterator from `.erase` and NOT through incrementing
       it = l.erase(it);
    }
    else {
       // no erasure; do the increment only in this case
       it++;
    }
}

正如Andy建议的那样,您可以通过使用标准算法来完全避免这个问题。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/16316899

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档