How to remove values from a QMap?

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?

Answers


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

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:

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.


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

  • 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.


Need Your Help

Eclipse Android gen already exists but is not a source folder

android eclipse

I am getting the following errors when I try to load an Android project in Eclipse that was working just fine last week.

How to use UIViewControllerAnimatedTransitioning with UINavigationController?

ios cocoa-touch ios7 xamarin.ios

How can I get custom transitions (iOS7) when pushing a view controller onto UINavigationController? I tried setting the TransitioningDelegate both in the UINavigationController and also on the cont...