1

Hello suppose that there is vector with 5 elements

vector<int> V;
for (int i=0;i<5;i++){
v.push_back(i);
}

Now how can I use find if and erase to erase values bigger than 2 from the vector ? Would you please suggest a sample code I prepared sth but I am not sure about that. THANKS

IMI
  • 105
  • 1
  • 1
  • 9

3 Answers3

5

You can use the erase-remove idiom using std::remove_if and a suitable functor. For example

V.erase(std::remove_if(std::begin(V), std::end(V),
                       [](int i){ return i > 2; } ), 
                       std::end(V) );

If you're stuck with a pre-C++11 compiler, then

bool func(int i) { return i > 2; }

V.erase(std::remove_if(V.begin(), V.end(), func), V.end());
juanchopanza
  • 223,364
  • 34
  • 402
  • 480
1

This is an alternate solution without using std::remove_if just using the erase method and iterators.

typedef std::vector<int> IntVector;
IntVector v;
// fill
for (IntVector::iterator it = v.begin(); it != v.end();) {
    if (*it > 2) {
        it = v.erase(it);
    } else {
        ++it;
    }
}
Flovdis
  • 2,945
  • 26
  • 49
  • I thought you were not supposed to modify the iterator variable inside the loop. – Marichyasana Apr 15 '14 at 21:56
  • @Marichyasana You can do it, if you do it right. The `erase` method returns a new valid iterator after removing the element from the vector. Note that you must not `++it` in this case. It's the reason why I do it in the `else` case and not in the `for` part. – Flovdis Apr 15 '14 at 21:58
1

You can remove from vector based on predicate (condition):

std::vector<int>::iterator it = std::remove_if(      // it shifts, doesn't 
                                v.begin(), v.end(),  // reduces the physical size
                                [](int i){ return i > 2; } ));

and erase unneeded values:

v.erase( it, v.end()); // this is needed as remove_if doesn't erase
                       // elements that don't meet condition (are not to be
                       // removed), it simply moves those that don't meet 
                       // condition to the begin.
                       // now we reduce the physical size

Why remove_if is followed by erase

Removing is done by shifting (by means of move assignment) the elements in the range in such a way that the elements that are not to be removed appear in the beginning of the range. Relative order of the elements that remain is preserved and the physical size of the container is unchanged. Iterators pointing to an element between the new logical end and the physical end of the range are still dereferenceable, but the elements themselves have unspecified values (as per MoveAssignable post-condition). A call to remove is typically followed by a call to a container's erase method, which erases the unspecified values and reduces the physical size of the container to match its new logical size.

http://en.cppreference.com/w/cpp/algorithm/remove

Example

// Let's imagine your vector is

v = { 1, 2, 3, 4, 5};
      ^              ^
      begin          end

// copy( v.begin(), v.end(), ostream_iterator<int>(cout));
will print: 12345

after remove_if vector becomes:

v = { 1, 2, 3, 4, 5};
      ^     ^        ^
      begin it       end
// copy( v.begin(), v.end(), ostream_iterator<int>(cout)); 
// will still print a vector of size 5: 12345
// but 

// copy( v.begin(), it, ostream_iterator<int>(cout));
will print: 12

after v.erase( it, v.end()); vector becomes:
v = { 1, 2};
      ^     ^
      begin end
// copy( v.begin(), v.end(), ostream_iterator<int>(cout));
will print: 12

compiled example


C++03:

bool f(int i) { return i > 2; }
std::vector<int>::iterator it = std::remove_if( v.begin(), v.end(), f); // shifts
v.erase( it, v.end());                               // reduces the physical size
4pie0
  • 29,204
  • 9
  • 82
  • 118
  • :perfect answer THANKS , sorry i am asking this question, since i am a beginner. i was wondering to know how the last proposed code works? – IMI Apr 15 '14 at 22:19
  • 1
    a pointer to the function, here to f, is passed to [remove_if](http://en.cppreference.com/w/cpp/algorithm/remove). This algorithm then evaluates the f(i) to check if condition is met or not and adjusts a vector accordingly - you can take a look at simplified pseudo-version of the algorithm in the link provided – 4pie0 Apr 15 '14 at 22:32
  • All solutions work perfectly, but i still have problem with the last one i prepared a code as below and i faced with error (there is an unmatched "{" in the code)!!!!!!! `int main() { vector v; v.push_back(1); v.push_back(2); v.push_back(3); v.push_back(4); v.push_back(5); vector::iterator it; bool f(int i) {return i > 2;} it = std::remove_if( v.begin(), v.end(), f); // shift v.erase( it, v.end()); }` – IMI Apr 15 '14 at 22:36
  • 1
    you can take a look at this: http://ideone.com/hw1W1w – 4pie0 Apr 15 '14 at 22:47