Reputation: 5181
I have a vector of elements of some type (with a name
member), and I want to filter (or copy) this vector so that it contains only the elements whose name matches a list of certain names. So basically: "Copy the element if its name is equal to any of the names in vector<string> filter
".
I've been trying stuff with std::copy_if
and std::any_of
, that resulted in code like below, but I couldn't get it to work, for once because any_of
can't be applied in this way, and I'm unsure of what the correct tools are in this case.
using namespace std;
template<class T>
struct MyType {
string name;
T data;
};
template<class T>
vector<MyType<T>> filter(vector<MyType<T>> items, vector<string> filter)
{
vector<MyType<T>> filteredItems;
copy_if(begin(items), end(items), begin(filteredItems), any_of(begin(filter), end(filter), [](const MyType<T>& lhs, const MyType<T>& rhs) {return lhs.name == rhs.name; }));
return filteredItems;
};
int main() {
vector<MyType<int>> items { {"a", 1}, {"b", 2}, {"c", 3} };
vector<string> filter { "a", "c" };
auto filteredItems = filter(items, filter);
}
How can I accomplish this, preferably with std::
functionality? (C++11/14 welcome)
Above code on ideone if you want to play around.
I guess this might be a good example to use ranges, but my code needs to compile on VS 2013 so I can't use https://github.com/ericniebler/range-v3 and I'm a bit hesitant to use an older ranges library, but I could be convinced otherwise.
Upvotes: 0
Views: 1202
Reputation: 137310
copy_if
is the right choice, but your predicate is wrong, and you need to use back_inserter
.
copy_if(begin(items), end(items), back_inserter(filteredItems),
[&](const MyType<T> & item) { return std::find(begin(filter), end(filter), item.name) != end(filter);} );
To find something in a range, use std::find
, which performs a simple linear search. If filter
is sorted, std::binary_search
can be used too.
Upvotes: 2