Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Keeping track of removed elements using std::remove_if

Tags:

c++

stl

I want to remove some elements from a vector and am using remove_if algorithm to do this. But I want to keep track of the removed elements so that I can perform some operation on them later. I tried this with the following code:

#include <vector>
#include <algorithm>
#include <iostream>

using namespace std;


struct IsEven
{
    bool operator()(int n) 
    {
        if(n % 2 == 0)
        {
            evens.push_back(n);
            return true;
        }

        return false;
    }

    vector<int> evens;
};

int main(int argc, char **argv)
{

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

    IsEven f;
    vector<int>::iterator newEnd = remove_if(v.begin(), v.end(), f);
    for(vector<int>::iterator it = f.evens.begin(); it != f.evens.end(); ++it)
    {
        cout<<*it<<"\n";
    }

    v.erase(newEnd, v.end());

    return 0;
}

But this doesn't work as remove_if accepts the copy of my functor object, so the the stored evens vector is not accessible. What is the correct way of achieving this?

P.S. : The example, with even and odds is just for example sake, my real code is somethinf different. So don't suggest a way to identify even or odds differently.

like image 290
Asha Avatar asked Mar 05 '12 08:03

Asha


1 Answers

The solution is not remove_if, but it's cousin partial_sort partition. The difference is that remove_if only guarantees that [begin, middle) contains the matching elements, but partition also guarantees that [middle, end) contains the elements which didn't match the predicate.

So, your example becomes just (note that evens is no longer needed):

vector<int>::iterator newEnd = partition(v.begin(), v.end(), f);
for(vector<int>::iterator it = newEnd; it != v.end(); ++it)
{
    cout<<*it<<"\n";
}
v.erase(newEnd, v.end());
like image 149
MSalters Avatar answered Sep 17 '22 22:09

MSalters