How to remove values ​​from QMap?

Suppose I want to remove items according to some criteria. Let them talk:

QMap<int, int> map; 

and I want to remove all elements where the 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 incorrect since the call

 map.remove(it.key()) 

invalidates the iterator. How can I do this without restarting the iterator after each deletion?

+6
source share
2 answers

Instead, use QMap::erase , which returns an iterator to the element next to the one you just deleted:

 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; 

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 can not check the last example at the moment.

+16
source

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

  • It takes an iterator as an argument and therefore does not waste time searching for an element by its key when you already know where it is;
  • It returns an iterator to the next element, so you can continue the iteration afterwards.

Using this, you can implement your loop correctly, like:

 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 can get the same result from map.remove((it++).key()) , but it will be slower and randomly than erase .

+4
source

Source: https://habr.com/ru/post/921495/


All Articles