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?
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:
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
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With