11

假设我想根据一些标准删除项目。比方说:

QMap<int, int> map;

我想删除所有值为奇数的项目。如果我使用迭代器:

for (auto it = map.begin(); it != map.end(); ++it)
    if (it.value() % 2 == 1)
        map.remove(it.key());

这段代码可能是错误的,因为调用

map.remove(it.key()) 

使迭代器无效。如何在每次删除后不重置迭代器的情况下做到这一点?

4

2 回答 2

28

改用QMap::erase它,它会返回一个迭代器,指向您刚刚删除的元素之后的元素:

for (auto it = map.begin(); it != map.end();)
    if (it.value() % 2 == 1)
        it = map.erase(it);
    else
        ++it;

另一种方法是在迭代器上使用后缀增量运算符:

for (auto it = map.begin(); it != map.end();)
    if (it.value() % 2 == 1)
        map.erase(it++);
    else
        ++it;

另一种方法(可能效率较低)是使用 STLremove_copy_if算法,然后是swap

bool valueIsOdd(int value) {return value % 2 == 1;}

QMap<int,int> b;
std::remove_copy_if(a.begin(), a.end(),
                    std::inserter(b, b.end()),
                    &valueIsOdd);
a.swap(b);

我目前无法测试最后一个示例。

于 2012-07-27T14:11:00.993 回答
5

你最好使用更像 STL 的erase函数:

  • 它将迭代器作为参数,因此当您已经知道它在哪里时,不会浪费时间通过它的键搜索元素;
  • 它返回一个指向下一个元素的迭代器,因此您可以在之后继续迭代。

使用它,您可以正确实现循环:

for (auto it = map.begin(); it != map.end(); /* don't increment here */) {
    if (it.value() % 2 == 1) {
        it = map.erase(it);
    } else {
        ++it;
    }
}

我认为您可以从 中获得相同的结果map.remove((it++).key()),但这会比erase.

于 2012-07-27T14:13:11.637 回答