push_back librerias libreria estandar espaƱol dev c++ stl

librerias - push_back c++



Borre/elimine contenidos del mapa(o cualquier otro contenedor STL) mientras lo itera (9)

1.For std::vector<> :

std::vector <int> vec; vec.erase(std::remove(vec.begin(),vec.end(), elem_to_remove), vec.end());

2. Para std::map<> siempre use std::map::erase()

std::map<int,std::string> myMap; myMap.emplace(std::make_pair(1, "Hello")); myMap.emplace(std::make_pair(2, "Hi")); myMap.emplace(std::make_pair(3, "How")); myMap.erase( 1);//Erase with key myMap.erase(myMap.begin(), ++myMap.begin() );//Erase with range for( auto &ele: myMap) { if(ele.first ==1) { myMap.erase(ele.first);//erase by key break; //You can''t use ele again properly //wthin this iteration, so break. } }

  1. Para std::list use std::list::erase()

Al parecer, no puede simplemente borrar / eliminar un elemento en un contenedor mientras se repite cuando el iterador se vuelve inválido. ¿Cuáles son las formas (seguras) de eliminar los elementos que cumplen una determinada condición? por favor solo stl, no boost o tr1.

EDITAR ¿Existe una forma más elegante si quiero borrar una serie de elementos que cumplen con ciertos criterios, tal vez con el uso de un algoritmo funtor y for_each o erase?


Ejemplo con std :: vector

#include <vector> using namespace std; int main() { typedef vector <int> int_vector; int_vector v(10); // Fill as: 0,1,2,0,1,2 etc for (size_t i = 0; i < v.size(); ++i){ v[i] = i % 3; } // Remove every element where value == 1 for (int_vector::iterator it = v.begin(); it != v.end(); /* BLANK */){ if (*it == 1){ it = v.erase(it); } else { ++it; } } }


La solución de Viktor tiene la ventaja de poder hacer algo con el elemento antes de quitarlo. (No pude hacer esto con remove_if o remove_copy_if .) Pero prefiero usar std::find_if para no tener que incrementar el iterador por mi cuenta:

typedef vector<int> int_vector; int_vector v; int_vector::iterator itr = v.begin(); for(;;) { itr = std::find_if(itr, v.end(), Predicate(4)); if (itr == v.end()) { break; } // do stuff with *itr here itr = v.erase(itr); // grab a new, valid iterator }

Donde Predicado podría ser bind1st( equal_to<int>(), 4 ) o algo como esto:

struct Predicate : public unary_function<int, bool> { int mExpected; Predicate(int desired) : mExpected(desired) {} bool operator() (int input) { return ( input == mExpected ); } };


Prefiero la versión con while :

typedef std::list<some_class_t> list_t; void f( void ) { // Remove items from list list_t::iterator it = sample_list.begin(); while ( it != sample_list.end() ) { if ( it->condition == true ) { it = sample_list.erase( it ); } else ++it; } }

Con while no hay peligro de incrementarlo dos veces, ya que podría estar dentro for bucle.


Puede hacerlo siempre que no invalide su iterador después de haberlo borrado:

MyContainer::iterator it = myContainer.begin(); while(it != myContainer.end()) { if (*it == matchingValue) { myContainer.erase(it++); } else { ++it; } }


Utilice el hecho de que el operador posterior al decremento devuelve una copia del iterador antes de decrementar. Dado que el iterador decrementado sigue siendo válido después de borrar el elemento actual, el bucle for continúa funcionando según lo previsto.

#include <list> std::list<int> myList; for(int i = 0; i < 10; ++i ) { myList.push_back(i); } int cnt = 0; for(std::list<int>::iterator iter = myList.begin(); iter != myList.end(); ++iter) { if( cnt == 5 ) { myList.erase(iter--); } ++cnt; }

Edición: no funciona si intenta borrar el primer elemento de la lista ...


markh44 es la respuesta más STL-ish. Sin embargo, tenga en cuenta que, en general, los iteradores se invalidan modificando el contenedor, pero set y map son excepciones. Allí, puede eliminar elementos y seguir utilizando los iteradores, excepto si elimina el mismo elemento al que hace referencia su iterador.


bool IsOdd( int i ) { return (i&1)!=0; } int a[] = {1,2,3,4,5}; vector<int> v( a, a + 5 ); v.erase( remove_if( v.begin(), v.end(), bind1st( equal_to<int>(), 4 ) ), v.end() ); // v contains {1,2,3,5} v.erase( remove_if( v.begin(), v.end(), IsOdd ), v.end() ); // v contains {2}


template <class Container, class Predicate> void eraseIf( Container& container, Predicate predicate ) { container.erase( remove_if( container.begin(), container.end(), predicate ), container.end() ); } // pre-c++11 version template<class K, class V, class Predicate> void eraseIf( std::map<K,V>& container, Predicate predicate) { typename std::map<K,V>::iterator iter = container.begin(); while(iter!=container.end()) { iterator current = iter++; if(predicate(*current)) container.erase(current); } } // c++11 version template<class K, class V, class Predicate> void eraseIf( std::map<K,V>& container, Predicate predicate) { auto iter = container.begin(); while(iter!=container.end()) { if(predicate(*iter)) iter = container.erase(iter); else ++iter; } }