1

我目前正在编写一个程序,该程序在所述程序中的某个点使用列表我想遍历 3 个三个列表 a、b 和 c,并删除 b 和 c 中的任何元素(如果它出现在 a 中)。我这样做:

//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);
                }
            }
        }
    }

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

4

3 回答 3

1

从您的擦除呼叫中,您想要

  1. 如果在 ClosedList 列表中找到 OpenList 项目,则删除它们
  2. 如果从 ClosedListlist 中找到邻居项,则删除它们

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

1.如果在 ClosedList 列表中找到 OpenList 项目,则删除它们

for(auto cloIt = ClosedList.begin(); cloIt != ClosedList.end(); ++cloIt)
{
   OpenList.remove_if([&](const Node& n){ return n == *colIt; } );
}

2.如果从 ClosedListlist 中找到邻居项,则删除它们

for(auto cloIt = ClosedList.begin(); cloIt != ClosedList.end(); ++cloIt)
{
   Neighbour.remove_if([&](const Node& n){ return n == *colIt; } );
}

显然之前的代码是重复的,您可以为此编写一个通用函数:

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

现在您可以致电:

RemoveItem(OpenList, CloseList);
RemoveItem(Neighbour, CloseList);

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

bool operator==(const Node& lhs, const Node& rhs)
{
  return lhs.getId() == rhs.getId();
}
于 2013-05-01T11:25:17.100 回答
0

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

(实际上你很幸运,你得到了一个试图增加你现在无效的迭代器的诊断——标准绝对不能保证这种情况。)

++ 当您不这样做时才需要.erase

一般模式如下所示:

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

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

于 2013-05-01T11:30:35.257 回答
0

我该如何解决这个问题?

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

您可以使用带有 lambda 谓词std::listremove_if()成员函数来检查元素是否包含在 list 中a

#include <algorithm>

// ...

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

c如果元素包含在a.

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

#include <algorithm>

// ...

std::for_each(begin(a), end(a),
    [&b, &c] (Node const& n)
    {
        b.remove(n);
        c.remove(n);
    });
于 2013-05-01T11:05:54.283 回答