Удалить диапазон элементов из QHash
Я использую QHash в качестве контейнера, и у меня есть задача удалить все элементы, которые удовлетворяют предикату. Сначала я подумал использовать идиому Erase-remove, оказалось, что QHash не имеет опции для удаления диапазона, а имеет только функцию для удаления одного элемента через итератор.
Функция std::unordered_map (концептуально близкая к QHash в Qt) имеет функцию удаления диапазона.
Это подразумевает вопрос: почему QHash не имеет аналогичной функции и как наилучшим образом удалить элементы из QHash, удовлетворяющие предикату?
2 ответа
На основании комментариев выясняется, что идиома удаления-удаления не относится к контейнеру QHash.
Поэтому дано описание QHash:: erase, в частности, что оно не нарушает порядок элементов в хэше
В отличие от remove() и take(), эта функция никогда не заставляет QHash перефразировать свою внутреннюю структуру данных. Это означает, что его можно безопасно вызывать во время итерации, и это не повлияет на порядок элементов в хэше.
у нас есть следующий код для удаления элементов, которые удовлетворяют предикату:
for( auto it = hash.begin(); it != hash.end(); ++it )
{
if( pred(*it) )
{
hash.erase(it);
}
}
Принятый ответ не работает, поскольку он игнорирует возвращаемое значение из erase(), которое является итератором для следующего элемента в хэше. Вам нужно сделать;
QHash<QObject *, int> objectHash;
QHash<QObject *, int>::iterator i = objectHash.begin();
while (i != objectHash.end()) {
if (i.value() == 0) { // test here
i = objectHash.erase(i);
} else {
++i;
}
согласно ссылке на документацию Qt - в противном случае вы увеличиваете недопустимый итератор.