@Brother Bob
std::set_intersection requires sorted ranges, which the OP hasn't definitively stated (though the example data is sorted, that could be human convenience).
@Alessandro
The following compiles for me:
#include <vector>
#include <functional>
#include <algorithm>
struct Example {
int id;
};
struct myPredicate : std::unary_function<Example, bool> {
myPredicate(int id) : id(id) {
}
bool operator()(const Example &obj) const {
return obj.id == id;
}
private:
int id;
};
void foo(std::vector<Example> &examples, const std::vector<int> &identifiers) {
for (unsigned i = 0 ; i < identifiers.size(); ++i) {
int id = identifiers[i];
examples.erase(std::remove_if(examples.begin(), examples.end(), std::not1(myPredicate(id))), examples.end());
}
}
Your code was incorrectly using std::unary_function (the first type parameter must match the parameter type of the operator().
Note that there are two simple ways of implementing this (naive) algorithm, essentially swapping the inner and outer loops. These have different performance characteristics, depending on the relative sizes of the two containers. You want the inner loop to be the smaller one, if you can predict this in advance (i.e. if there are always less identifiers than objects, then the identifiers should be the inner loop).
If this is a performance sensitive application and you are frequently attempting to look up an item by ID, you may also want to consider storing the data in a more search friendly manner, e.g. a binary tree or hash map based on identifier. You could also sort the list of identifiers, this way you can quickly binary search for a given element.
If both ranges are sorted, then you can use some of the more advanced C++ algorithms to help you, as Brother Bob is suggesting. You would need, of course, to balance the cost of lookups against the iteration cost (if you frequently visit the entire collection) and the insert/removal cost (depending on frequency of insertion/removal, and in particular if you need random access insertion).