如何从QMap中删除值?

时间:2021-05-17 19:34:53

Suppose I want to remove items according to some criterium. Let's say:

假设我要根据一些标准来移除项。比方说:

QMap<int, int> map;

and I want to remove all the items where value is an odd number. If I use an iterator:

我想要移除所有的项,其中值是一个奇数。如果我使用迭代器:

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

This code is probably wrong, since the call of

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

map.remove(it.key()) 

invalidates the iterator. How can I do this without reseting the iterator after each removal?

迭代器将会失效。如何在每次删除之后不重新设置迭代器呢?

2 个解决方案

#1


17  

Use QMap::erase instead, which returns an iterator to the element following the one you just erased:

使用QMap:::擦除,它返回一个迭代器到元素的后面,紧跟着刚才擦除的元素:

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

Another way is to use the postfix increment operator on the iterator:

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

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

Yet another way (and probably less efficient) is to use the STL remove_copy_if algorithm, followed by swap:

另一种方法(可能效率更低)是使用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);

I cannot test the last example at the moment.

我现在不能测试最后一个例子。

#2


4  

You would be better off using the more STL-like erase function:

你最好使用更像stl的擦除功能:

  • It takes an iterator as an argument, and so doesn't waste time searching for the element by its key when you already know where it is;
  • 它使用迭代器作为参数,因此,当您已经知道它的位置时,它不会浪费时间搜索元素;
  • It returns an iterator to the next element, so you can carry on iterating afterwards.
  • 它将迭代器返回到下一个元素,因此您可以在之后进行迭代。

Using this, you can implement your loop correctly as:

使用此方法,您可以正确地实现循环,如:

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

I think you could get the same result from map.remove((it++).key()), but that would be both slower and messier than erase.

我认为从map.remove((it+).key() .key())中可以得到相同的结果,但是这比erase要慢得多,也更混乱。

#1


17  

Use QMap::erase instead, which returns an iterator to the element following the one you just erased:

使用QMap:::擦除,它返回一个迭代器到元素的后面,紧跟着刚才擦除的元素:

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

Another way is to use the postfix increment operator on the iterator:

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

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

Yet another way (and probably less efficient) is to use the STL remove_copy_if algorithm, followed by swap:

另一种方法(可能效率更低)是使用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);

I cannot test the last example at the moment.

我现在不能测试最后一个例子。

#2


4  

You would be better off using the more STL-like erase function:

你最好使用更像stl的擦除功能:

  • It takes an iterator as an argument, and so doesn't waste time searching for the element by its key when you already know where it is;
  • 它使用迭代器作为参数,因此,当您已经知道它的位置时,它不会浪费时间搜索元素;
  • It returns an iterator to the next element, so you can carry on iterating afterwards.
  • 它将迭代器返回到下一个元素,因此您可以在之后进行迭代。

Using this, you can implement your loop correctly as:

使用此方法,您可以正确地实现循环,如:

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

I think you could get the same result from map.remove((it++).key()), but that would be both slower and messier than erase.

我认为从map.remove((it+).key() .key())中可以得到相同的结果,但是这比erase要慢得多,也更混乱。