Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Erase/Remove contents from the map (or any other STL container) while iterating it

Tags:

c++

stl

People also ask

How do I remove something from a map in C++?

map::clear() function is an inbuilt function in C++ STL, which is defined in header file. clear() is used to remove all the content from the associated map container. This function removes all the values and makes the size of the container as 0.

How do I delete a container in St Louis?

If you store pointers in STL container classes you need to manually delete them before the object gets destroyed. This can be done by looping through the whole container and deleting each item, or by using some kind of smart pointer class. However do not use auto_ptr as that just does not work with containers at all.

What is the use of iterate over container in STL?

An iterator is used to point to the memory address of the STL container classes. For better understanding, you can relate them with a pointer, to some extent. Iterators act as a bridge that connects algorithms to STL containers and allows the modifications of the data present inside the container.

How do I get rid of STD map?

The standard approach to remove elements from a map is using the std::map::erase member function. It offers several overload versions. The first overload version accepts an iterator pointing to an element that needs to be removed from the map.


You can as long as you don't invalidate your iterator after you've erased it:

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

Example with 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;
      }
   }

}

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}

Viktor's solution has the upside of being able to do something with the element before removing. (I wasn't able to do this with remove_if or remove_copy_if.) But I prefer to use std::find_if so I never have to increment the iterator myself:

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
}

Where Predicate could be bind1st( equal_to<int>(), 4 ) or something like this:

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

I prefer version with 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;    
  }
}

With while there is no danger to increment it twice as it could be in for loop.


1.For std::vector<> :

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

2.For std::map<> always 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. For std::list use std::list::erase()