2010-01-18 9 views
10

Soy nuevo en C++. Me gustaría saber cómo los codificadores experimentados hacen esto.cómo eliminar todos los enteros pares del conjunto <int> en C++

lo que tengo:

set<int> s; 
s.insert(1); 
s.insert(2); 
s.insert(3); 
s.insert(4); 
s.insert(5); 

for(set<int>::iterator itr = s.begin(); itr != s.end(); ++itr){ 
if (!(*itr % 2)) 
    s.erase(itr); 
} 

y, por supuesto, que no funciona. porque itr se incrementa después de que se borre. ¿significa que Itr debe señalar el inicio del conjunto cada vez que elimine el elemento del conjunto?

Respuesta

16
for(set<int>::iterator itr = s.begin(); itr != s.end();){ 
    if (!(*itr % 2)) 
     s.erase(itr++); 

    else ++itr; 
} 

STL efectiva por Scott Myers

+0

Tiene un paréntesis adicional en el código. – qba

+0

¿por qué se permite itr ++ en la función de borrado, pero no en el exterior? – Quincy

+5

'itr ++' está permitido afuera, pero '++ it' es en general preferible cuando el valor no se usa, por razones tediosas para entrar cada vez que alguien lo hace ;-) En este caso, podría ser mejor ignore las buenas prácticas habituales y escriba 'itr ++', simplemente porque el código se lee un poco más suave si es el mismo en ambos casos. –

11

Al borrar un elemento de std :: set solo se invalidan los iteradores que apuntan a ese elemento.

Obtenga un iterador para el siguiente elemento antes de borrar el elemento de destino.

8

No necesita volver al comienzo. set::erase sólo se invalida iteradores que se refieren al tema que se borren, por lo que sólo tiene que copiar el iterador y la subasta antes de borrar:

for(set<int>::iterator itr = s.begin(); itr != s.end();) 
{ 
    set<int>::iterator here = itr++; 
    if (!(*here % 2)) 
     s.erase(here); 
} 
+0

OK, me rindo. ¿Cuál es el error? –

+1

Estaba equivocado, pensé que estabas omitiendo el primer elemento. Retiro mi comentario y voto negativo. –

-1

La mejor manera es utilizar la combinación de remove_if y borrar

s.erase(remove_if(s.begin(), s.end(), evenOddFunctor), s.end()) 

Esto será útil http://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Erase-Remove

también se refieren a STL efectiva por Meyers scott

Edit: A pesar de que mi solución es incorrecto No estoy eliminarlo. Podría ser un buen aprendizaje para alguien como yo que no se refiere a los iteradores mutables/inmutables

+6

'remove_if' requiere que' operator * 'devuelva un valor l no const. std :: set impone que siempre esté ordenado; devolver una lvalue no const de 'std :: set :: operator *' rompería esa garantía. Por lo tanto, 'std :: remove_if()' no toma 'std :: set :: iterator's – MSalters

+0

Gracias, no sé si –

+5

Eso fue realmente útil. Estuve atascado tratando de hacer esto con remove_if y esto me dijo cuál era el problema. Gracias. –

Cuestiones relacionadas