如何从QMap中删除值?

Mar*_*dik 11 c++ qt iterator

假设我想根据一些标准删除项目.让我们说:

QMap<int, int> map;
Run Code Online (Sandbox Code Playgroud)

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

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

这个代码可能是错的,因为调用了

map.remove(it.key()) 
Run Code Online (Sandbox Code Playgroud)

使迭代器无效.如何在每次删除后不重置迭代器的情况下执行此操作?

Emi*_*ier 24

QMap::erase相反,使用它返回一个迭代器到你刚删除的元素之后的元素:

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

另一种方法是在迭代器上使用postfix increment运算符:

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

另一种方式(可能效率较低)是使用STL remove_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);
Run Code Online (Sandbox Code Playgroud)

我现在无法测试最后一个例子.

  • 如果你没有删除元素,你应该只增加`it`; 否则,你会错过下一个元素. (3认同)

Mik*_*our 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

我认为你可以从中得到相同的结果map.remove((it++).key()),但这会比它更慢,更麻烦erase.