Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use STL to populate a vector<T> from map<T,Z>'s keys

Tags:

c++

stl

map<T,Z> m= ...;
vector<T> v;
v.reserve(m.size);
for(map<T,Z>::iterator it=m.begin();it!=m.end();++it)
{
 v.push_back(it->first);
}

Is there a nicer 1-line version using some STL function(s)?

edit: not using c++11!

like image 555
Mr. Boy Avatar asked Oct 05 '11 20:10

Mr. Boy


1 Answers

Portable:

struct SelectKey {
  template <typename F, typename S>
  F operator()(const std::pair<const F, S> &x) const { return x.first; }
};

std::transform(m.cbegin(), m.cend(), std::back_inserter(v), SelectKey());

I think some implementations of STL have a non-standard extension called select1st, which is the equivalent of SelectKey shown here. As K-Ballo pointed out in the comments, there's also a TR1 version. I like the explicitly-named version as it's easier to see what's going on.

Since there's no need for state, you can get away with slightly less boilerplate by using an actual function rather than a functor:

template <typename F, typename S>
F SelectKey()(const std::pair<const F, S> &x) { return x.first; }

std::transform(m.cbegin(), m.cend(), std::back_inserter(v), SelectKey);

If you could use C++11, you could use a lambda, which keeps the selection code close to where it's used:

std::transform(m.cbegin(), m.cend(), std::back_inserter(v),
               [](const std::pair<const F, S> &x) { return x.first; });

or even range-based for-loop, which is probably the most elegant and readable:

for(const auto &x : m) {
  v.push_back(x.first);
}
like image 199
Adrian McCarthy Avatar answered Sep 17 '22 15:09

Adrian McCarthy