I'm trying to implement, in STL fashion, an algorithm with the following functionallity:
Given a range [first,last)
, a neighborhood span nSpan
and a (binary) predicate Pred
, it removes elements from that range, so that Pred
is NOT true for any remaining elements distant from each other at most nSpan
Examples :
In the last example, it's obvious that (to prevent the algorithm from going ambiguous) we sweep from the first iterator and on, while checking up to nSpan distance to remove elements (otherwise there would be multiple ways to remove elements).
My attempt so far (code listing below) has the following shortcomings:
- After a first sweep the new range may have new elements that are invalid, so a recursive functionality (again scaning from the new start towards the end) is needed to rescan the range (or maybe immitate recursion every time a removal happens)
- It's not implemented as a
remove
function but as an erase
one (I need a remove one and it seems significantly more difficult) and that forces to supply the whole container as an argument instead of a range (ideally the algorithm should be container agnostic)
I'm listing a first attempt
template<typename Cont, typename It, class Pr>
void erase_neighbors(Cont &cont, It first, It last, int nSpan, Pr Pred)
{
if (0 < nSpan && nSpan < std::distance(first, last)) for (It it2; (it2 = first), first != last; )
{
if (nSpan < std::distance(it2, last))
{
std::advance(it2, nSpan);
if (Pred(*first, *it2))
{
first = cont.erase(first, it2);
last = cont.end();
continue;
}
}
++first;
}
}
Ideal signature
template<typename It, class Pr>
It remove_neighbors(It first, It last, int nSpan, Pr Pred);
Ideal implementation : non c++11 and without boost (even though if there is a related boost algorithm I would appreciate knowing about it)