c++ - ¿Cómo puedo eliminar elementos de una QList mientras la repito utilizando foreach?
qt (3)
Debería usar iteradores para eso:
// Remove all odd numbers from a QList<int>
QMutableListIterator<int> i(list);
while (i.hasNext()) {
if (i.next() % 2 != 0)
i.remove();
}
Soy nuevo en Qt e intento aprender los modismos.
La documentación de foreach
dice:
Qt toma automáticamente una copia del contenedor cuando ingresa a un ciclo foreach. Si modifica el contenedor mientras itera, eso no afectará al bucle.
Pero no dice cómo eliminar un elemento mientras itera con foreach
. Mi mejor suposición es algo así como:
int idx = 0;
foreach (const Foo &foo, fooList) {
if (bad(foo)) {
fooList.removeAt(idx);
}
++idx;
}
Parece feo tener que idx
el idx
fuera del bucle (y tener que mantener un contador de bucle por separado).
Además, sé que Sí, ocurre una copia profunda . foreach
hace una copia de la QList
, que es barata, pero ¿qué ocurre una vez que elimino un elemento? ¿Sigue siendo barata o hay una costosa copia en modificación?
EDITAR: Esto tampoco parece Qt idiomático.
for (int idx = 0; idx < fooList.size(); ) {
const Foo &foo = fooList[idx];
if (bad(foo)) {
fooList.removeAt(idx);
}
else ++idx;
}
Si la función de prueba es reentrante, también puede usar QtConcurrent para eliminar los elementos "malos":
#include <QtCore/QtConcurrentFilter>
...
QtConcurrent::blockingFilter(fooList, bad);
O la variante STL:
#include <algorithm>
...
fooList.erase(std::remove_if(fooList.begin(), fooList.end(), bad),
fooList.end());
Si no quiere una copia, use iteradores. Algo como:
QList<yourtype>::iterator it = fooList.begin();
while (it != fooList.end()) {
if (bad(*it))
it = fooList.erase(it);
else
++it;
}
(Y asegúrese de que realmente quiera usar una QList
lugar de una QLinkedList
).
foreach
es realmente agradable cuando desea recorrer una colección para su inspección, pero como ha descubierto, es difícil razonar sobre cuándo quiere cambiar la estructura de la colección subyacente (no los valores almacenados allí). Así que lo evito en ese caso, simplemente porque no puedo determinar si es seguro o cuánto se sobrecarga la copia.