Как удалить значения из QMap?
предположим, я хочу удалить элементы в соответствии с некоторым критерием. Скажем:
QMap<int, int> map;
и я хочу удалить все элементы, где значение нечетное число. Если я использую итератор:
for (auto it = map.begin(); it != map.end(); ++it)
if (it.value() % 2 == 1)
map.remove(it.key());
этот код, вероятно, неправильный, так как вызов
map.remove(it.key())
инвалидирует итератор. Как я могу это сделать без сброса итератора после каждого удаления?
2 ответов
использовать QMap::erase
вместо этого, который возвращает итератор к элементу, следующему за тем, который вы только что удалили:
for (auto it = map.begin(); it != map.end();)
if (it.value() % 2 == 1)
it = map.erase(it);
else
++it;
другой способ-использовать постфиксного инкремента оператор на итератор:
for (auto it = map.begin(); it != map.end();)
if (it.value() % 2 == 1)
map.erase(it++);
else
++it;
еще один способ (и, вероятно, менее эффективный) - использовать 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);
Я не могу проверить последний пример на данный момент.
вам было бы лучше использовать более STL-like erase
функция:
- он принимает итератор в качестве аргумента и поэтому не тратит время на поиск элемента по его ключу, когда вы уже знаете, где он находится;
- он возвращает итератор к следующему элементу, поэтому вы можете продолжить итерацию после этого.
используя это, вы можете правильно реализовать свой цикл как:
for (auto it = map.begin(); it != map.end(); /* don't increment here */) {
if (it.value() % 2 == 1) {
it = map.erase(it);
} else {
++it;
}
}
Я думаю, вы могли бы получить то же самое результат от map.remove((it++).key())
, но это было бы медленнее и грязнее, чем erase
.