Suppose I have the following two data structures:
std::vector<int> all_items;
std::set<int> bad_items;
The all_items
vector contains all known items and the bad_items
vector contains a list of bad items. These two data structures are populated entirely independent of one another.
What's the proper way to write a method that will return a std::vector<int>
contain all elements of all_items
not in bad_items
?
Currently, I have a clunky solution that I think can be done more concisely. My understanding of STL function adapters is lacking. Hence the question. My current solution is:
struct is_item_bad {
std::set<int> const* bad_items;
bool operator() (int const i) const {
return bad_items.count(i) > 0;
}
};
std::vector<int> items() const {
is_item_bad iib = { &bad_items; };
std::vector<int> good_items(all_items.size());
std::remove_copy_if(all_items.begin(), all_items.end(),
good_items.begin(), is_item_bad);
return good_items;
}
Assume all_items
, bad_items
, is_item_bad
and items()
are all a part of some containing class. Is there a way to write them items()
getter such that:
- It doesn't need temporary variables in the method?
- It doesn't need the custom functor,
struct is_item_bad
?
I had hoped to just use the count
method on std::set
as a functor, but I haven't been able to divine the right way to express that w/ the remove_copy_if
algorithm.
EDIT: Fixed the logic error in items()
. The actual code didn't have the problem, it was a transcription error.
EDIT: I have accepted a solution that doesn't use std::set_difference
since it is more general and will work even if the std::vector
isn't sorted. I chose to use the C++0x lambda expression syntax in my code. My final items()
method looks like this:
std::vector<int> items() const {
std::vector<int> good_items;
good_items.reserve(all_items.size());
std::remove_copy_if(all_items.begin(), all_items.end(),
std::back_inserter(good_items),
[&bad_items] (int const i) {
return bad_items.count(i) == 1;
});
}
On a vector of about 8 million items the above method runs in 3.1s. I bench marked the std::set_difference
approach and it ran in approximately 2.1s. Thanks to everyone who supplied great answers.