Как удалить значения из 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.