Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Erasing elements from a vector

I want to clear a element from a vector using the erase method. But the problem here is that the element is not guaranteed to occur only once in the vector. It may be present multiple times and I need to clear all of them. My code is something like this:

void erase(std::vector<int>& myNumbers_in, int number_in) {     std::vector<int>::iterator iter = myNumbers_in.begin();     std::vector<int>::iterator endIter = myNumbers_in.end();     for(; iter != endIter; ++iter)     {         if(*iter == number_in)         {             myNumbers_in.erase(iter);         }     } }  int main(int argc, char* argv[]) {     std::vector<int> myNmbers;     for(int i = 0; i < 2; ++i)     {         myNmbers.push_back(i);         myNmbers.push_back(i);     }      erase(myNmbers, 1);      return 0; } 

This code obviously crashes because I am changing the end of the vector while iterating through it. What is the best way to achieve this? I.e. is there any way to do this without iterating through the vector multiple times or creating one more copy of the vector?

like image 761
Naveen Avatar asked Dec 07 '08 10:12

Naveen


People also ask

How do you remove an element from a value in vector?

You need to use std::remove algorithm to move the element to be erased to the end of the vector and then use erase function. Something like: myVector. erase(std::remove(myVector. begin(), myVector.

How do I remove multiple elements from a vector file?

If you need to remove multiple elements from the vector, the std::remove will copy each, not removed element only once to its final location, while the vector::erase approach would move all of the elements from the position to the end multiple times.

Which method removes all elements from vector?

clear() method is used to remove all the elements from a Vector. Using the clear() method only clears all the element from the vector and does not delete the vector.

How do you remove an object from a vector?

The erase() function can remove an element from the beginning, within, or end of the vector. In order to remove all the elements from the vector, using erase(), the erase() function has to be repeated the number of times there are elements, beginning from the first element.


2 Answers

Use the remove/erase idiom:

std::vector<int>& vec = myNumbers; // use shorter name vec.erase(std::remove(vec.begin(), vec.end(), number_in), vec.end()); 

What happens is that remove compacts the elements that differ from the value to be removed (number_in) in the beginning of the vector and returns the iterator to the first element after that range. Then erase removes these elements (whose value is unspecified).

like image 114
Motti Avatar answered Sep 21 '22 02:09

Motti


Calling erase will invalidate iterators, you could use:

void erase(std::vector<int>& myNumbers_in, int number_in) {     std::vector<int>::iterator iter = myNumbers_in.begin();     while (iter != myNumbers_in.end())     {         if (*iter == number_in)         {             iter = myNumbers_in.erase(iter);         }         else         {            ++iter;         }     }  } 

Or you could use std::remove_if together with a functor and std::vector::erase:

struct Eraser {     Eraser(int number_in) : number_in(number_in) {}     int number_in;     bool operator()(int i) const     {         return i == number_in;     } };  std::vector<int> myNumbers; myNumbers.erase(std::remove_if(myNumbers.begin(), myNumbers.end(), Eraser(number_in)), myNumbers.end()); 

Instead of writing your own functor in this case you could use std::remove:

std::vector<int> myNumbers; myNumbers.erase(std::remove(myNumbers.begin(), myNumbers.end(), number_in), myNumbers.end()); 

In C++11 you could use a lambda instead of a functor:

std::vector<int> myNumbers; myNumbers.erase(std::remove_if(myNumbers.begin(), myNumbers.end(), [number_in](int number){ return number == number_in; }), myNumbers.end()); 

In C++17 std::experimental::erase and std::experimental::erase_if are also available, in C++20 these are (finally) renamed to std::erase and std::erase_if (note: in Visual Studio 2019 you'll need to change your C++ language version to the latest experimental version for support):

std::vector<int> myNumbers; std::erase_if(myNumbers, Eraser(number_in)); // or use lambda 

or:

std::vector<int> myNumbers; std::erase(myNumbers, number_in); 
like image 34
dalle Avatar answered Sep 20 '22 02:09

dalle