erase-remove_if idiom - was anything removed?

2k Views Asked by At

I'm creating an API which users will call to remove items from an internal vector. They will pass in criteria to search the vector for elements to remove. I'd like my API to return a boolean for if any elements were found and removed.

I'm planning on using the erase-remove idiom to keep things simple and efficient. I don't see an obvious way right off to detect that items were actually removed? Is storing the number of elements in the vector before removing, and comparing the value, my best bet?

Here is some (untested) sample code on this idiom:

std::vector<int> v = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };

boolean removeMultiples(int multiple) {
    v.erase( std::remove_if(v.begin(), v.end(), [multiple](int i){return i%multiple == 0;}), v.end() );
    // return true if anything was removed
}
3

There are 3 best solutions below

2
On BEST ANSWER

One idea would be to store the return value of std::remove_if, and compare it with the containers end() iterator before doing the erase like this:

bool removeMultiples(int multiple)
{
    auto it = std::remove_if(v.begin(), v.end(), [multiple](int i){return i%multiple == 0;});
    bool any_change = it != v.end();
    v.erase(it, v.end());
    return any_change;
}
0
On

There is no need to write the algorithms in one line. You can for example write

bool removeMultiples( int multiple )
{
    bool success;

    auto it = std::remove_if(v.begin(), v.end(), [multiple](int i){return i%multiple == 0;});

    if ( ( success = it != v.end() ) ) v.erase( it, v.end() );

    return success;
}
0
On
template<class C, class F>
bool remove_some(C&c, F&&f){
  using std::begin; using std::end;
  auto it = std::remove_if(begin(c), end(c), std::forward<F>(f) );
  bool r = it!=end(c);
  c.erase(it, end(c));
  return r;
}

then

bool removeMultiples(std::vector<int>& f, int multiple) {
  return remove_some(v, [multiple](int i){return !(i%multiple);});
}

is simple and clean.