David
David

Reputation: 11

Remove elements from a c++ vector where the removal condition is dependent on other elements

The standard way to remove certain elements from a vector in C++ is the remove/erase idiom. However, the predicate passed to remove_if only takes the vector element under consideration as an argument. Is there a good STL way to do this if the predicate is conditional on other elements of the array?

To give a concrete example, consider removing all duplicates of a number immediately following it. Here the condition for removing the n-th element is conditional on the (n-1)-th element.

Before: 11234555111333
After: 1234513

Upvotes: 1

Views: 951

Answers (3)

Xeo
Xeo

Reputation: 131799

Others mentioned std::unique already, for your specific example. Boost.Range has the adjacent_filtered adaptor, which passes both the current and the next element in the range to your predicate and is, thanks to the predicate, applicable to a larger range of problems. Boost.Range however also has the uniqued adaptor.

Another possibility would be to simply keep a reference to the range, which is easy to do with a lambda in C++11:

std::vector<T> v;
v.erase(std::remove_if(v.begin(), v.end(), 
    [&](T const& x){
      // use v, with std::find for example
    }), v.end());

Upvotes: 2

innochenti
innochenti

Reputation: 1103

In my opinion, there will be easier to use simple traversal algorithm(via for) rather then use std::bind. Of course, with std::bind you can use other functions and predicates(which depends on previous elements). But in your example, you can do it via simple std::unique.

Upvotes: 0

jrok
jrok

Reputation: 55395

There's a standard algorithm for this. std::unique will remove the elements that are duplicates of those preceding them (actually, just like remove_if it reorganizes the container so that the elements to be removed are gathered at the end of it).

Example on a std::string for simplicity:

#include <string>
#include <iostream>
#include <algorithm>

int main()
{
    std::string str = "11234555111333";
    str.erase(std::unique(str.begin(), str.end()), str.end());
    std::cout << str;   // 1234513
}

Upvotes: 2

Related Questions